[commit] r3763 - in freeswitch/trunk/libs/libetpan: . build-windows build-windows/libetpan build-windows/readmsg build-windows/smtpsend doc doc/API doc/README src src/bsd src/data-types src/driver src/driver/implementation src/driver/implementation/data-message src/driver/implementation/db src/driver/implementation/hotmail src/driver/implementation/imap src/driver/implementation/maildir src/driver/implementation/mbox src/driver/implementation/mh src/driver/implementation/mime-message src/dr
Author: mikej Date: Wed Dec 20 15:28:56 2006 New Revision: 3763 Added: freeswitch/trunk/libs/libetpan/ (props changed) freeswitch/trunk/libs/libetpan/.cvsignore freeswitch/trunk/libs/libetpan/COPYRIGHT freeswitch/trunk/libs/libetpan/ChangeLog freeswitch/trunk/libs/libetpan/INSTALL freeswitch/trunk/libs/libetpan/Makefile.in freeswitch/trunk/libs/libetpan/NEWS freeswitch/trunk/libs/libetpan/Rules.in freeswitch/trunk/libs/libetpan/TODO freeswitch/trunk/libs/libetpan/aclocal.m4 freeswitch/trunk/libs/libetpan/autogen.sh (contents, props changed) freeswitch/trunk/libs/libetpan/build-windows/ freeswitch/trunk/libs/libetpan/build-windows/README.txt freeswitch/trunk/libs/libetpan/build-windows/StdAfx.h freeswitch/trunk/libs/libetpan/build-windows/build_headers.bat freeswitch/trunk/libs/libetpan/build-windows/build_headers.list freeswitch/trunk/libs/libetpan/build-windows/libetpan/ freeswitch/trunk/libs/libetpan/build-windows/libetpan-config.h freeswitch/trunk/libs/libetpan/build-windows/libetpan.sln freeswitch/trunk/libs/libetpan/build-windows/libetpan/libetpan.vcproj freeswitch/trunk/libs/libetpan/build-windows/libetpan_version.h freeswitch/trunk/libs/libetpan/build-windows/readmsg/ freeswitch/trunk/libs/libetpan/build-windows/readmsg/readmsg.vcproj freeswitch/trunk/libs/libetpan/build-windows/smtpsend/ freeswitch/trunk/libs/libetpan/build-windows/smtpsend/smtpsend.vcproj freeswitch/trunk/libs/libetpan/config.guess (contents, props changed) freeswitch/trunk/libs/libetpan/config.h.in freeswitch/trunk/libs/libetpan/config.sub (contents, props changed) freeswitch/trunk/libs/libetpan/configure (contents, props changed) freeswitch/trunk/libs/libetpan/configure.in freeswitch/trunk/libs/libetpan/doc/ freeswitch/trunk/libs/libetpan/doc/.cvsignore freeswitch/trunk/libs/libetpan/doc/API/ freeswitch/trunk/libs/libetpan/doc/API.html freeswitch/trunk/libs/libetpan/doc/API.sgml freeswitch/trunk/libs/libetpan/doc/API.txt freeswitch/trunk/libs/libetpan/doc/API/book1.htm freeswitch/trunk/libs/libetpan/doc/API/c13.htm freeswitch/trunk/libs/libetpan/doc/API/c1586.htm freeswitch/trunk/libs/libetpan/doc/API/c16.htm freeswitch/trunk/libs/libetpan/doc/API/c2988.htm freeswitch/trunk/libs/libetpan/doc/API/c385.htm freeswitch/trunk/libs/libetpan/doc/API/x1094.htm freeswitch/trunk/libs/libetpan/doc/API/x1381.htm freeswitch/trunk/libs/libetpan/doc/API/x1556.htm freeswitch/trunk/libs/libetpan/doc/API/x161.htm freeswitch/trunk/libs/libetpan/doc/API/x1614.htm freeswitch/trunk/libs/libetpan/doc/API/x2180.htm freeswitch/trunk/libs/libetpan/doc/API/x229.htm freeswitch/trunk/libs/libetpan/doc/API/x2583.htm freeswitch/trunk/libs/libetpan/doc/API/x2669.htm freeswitch/trunk/libs/libetpan/doc/API/x289.htm freeswitch/trunk/libs/libetpan/doc/API/x2946.htm freeswitch/trunk/libs/libetpan/doc/API/x3011.htm freeswitch/trunk/libs/libetpan/doc/API/x3015.htm freeswitch/trunk/libs/libetpan/doc/API/x3082.htm freeswitch/trunk/libs/libetpan/doc/API/x312.htm freeswitch/trunk/libs/libetpan/doc/API/x3198.htm freeswitch/trunk/libs/libetpan/doc/API/x3472.htm freeswitch/trunk/libs/libetpan/doc/API/x425.htm freeswitch/trunk/libs/libetpan/doc/API/x88.htm freeswitch/trunk/libs/libetpan/doc/DOCUMENTATION freeswitch/trunk/libs/libetpan/doc/Makefile freeswitch/trunk/libs/libetpan/doc/README/ freeswitch/trunk/libs/libetpan/doc/README.html freeswitch/trunk/libs/libetpan/doc/README.sgml freeswitch/trunk/libs/libetpan/doc/README.txt freeswitch/trunk/libs/libetpan/doc/README/book1.htm freeswitch/trunk/libs/libetpan/doc/README/c13.htm freeswitch/trunk/libs/libetpan/doc/README/c157.htm freeswitch/trunk/libs/libetpan/doc/README/c53.htm freeswitch/trunk/libs/libetpan/doc/README/x19.htm freeswitch/trunk/libs/libetpan/doc/README/x82.htm freeswitch/trunk/libs/libetpan/doc/README/x94.htm freeswitch/trunk/libs/libetpan/doc/depend.dot freeswitch/trunk/libs/libetpan/doc/layer.fig freeswitch/trunk/libs/libetpan/install-sh (contents, props changed) freeswitch/trunk/libs/libetpan/libetpan-config.h.in freeswitch/trunk/libs/libetpan/libetpan-config.in (contents, props changed) freeswitch/trunk/libs/libetpan/ltmain.sh freeswitch/trunk/libs/libetpan/src/ (props changed) freeswitch/trunk/libs/libetpan/src/.cvsignore freeswitch/trunk/libs/libetpan/src/Makefile.in freeswitch/trunk/libs/libetpan/src/bsd/ freeswitch/trunk/libs/libetpan/src/bsd/getopt.c freeswitch/trunk/libs/libetpan/src/bsd/getopt.h freeswitch/trunk/libs/libetpan/src/bsd/getopt_long.c freeswitch/trunk/libs/libetpan/src/data-types/ (props changed) freeswitch/trunk/libs/libetpan/src/data-types/.cvsignore freeswitch/trunk/libs/libetpan/src/data-types/Makefile freeswitch/trunk/libs/libetpan/src/data-types/base64.c freeswitch/trunk/libs/libetpan/src/data-types/base64.h freeswitch/trunk/libs/libetpan/src/data-types/carray.c freeswitch/trunk/libs/libetpan/src/data-types/carray.h freeswitch/trunk/libs/libetpan/src/data-types/charconv.c freeswitch/trunk/libs/libetpan/src/data-types/charconv.h freeswitch/trunk/libs/libetpan/src/data-types/chash.c freeswitch/trunk/libs/libetpan/src/data-types/chash.h freeswitch/trunk/libs/libetpan/src/data-types/cinthash.c freeswitch/trunk/libs/libetpan/src/data-types/cinthash.h freeswitch/trunk/libs/libetpan/src/data-types/clist.c freeswitch/trunk/libs/libetpan/src/data-types/clist.h freeswitch/trunk/libs/libetpan/src/data-types/connect.c freeswitch/trunk/libs/libetpan/src/data-types/connect.h freeswitch/trunk/libs/libetpan/src/data-types/hmac-md5.h freeswitch/trunk/libs/libetpan/src/data-types/mail.h freeswitch/trunk/libs/libetpan/src/data-types/mail_cache_db.c freeswitch/trunk/libs/libetpan/src/data-types/mail_cache_db.h freeswitch/trunk/libs/libetpan/src/data-types/mail_cache_db_types.h freeswitch/trunk/libs/libetpan/src/data-types/maillock.c freeswitch/trunk/libs/libetpan/src/data-types/maillock.h freeswitch/trunk/libs/libetpan/src/data-types/mailsasl.c freeswitch/trunk/libs/libetpan/src/data-types/mailsasl.h freeswitch/trunk/libs/libetpan/src/data-types/mailsem.c freeswitch/trunk/libs/libetpan/src/data-types/mailsem.h freeswitch/trunk/libs/libetpan/src/data-types/mailstream.c freeswitch/trunk/libs/libetpan/src/data-types/mailstream.h freeswitch/trunk/libs/libetpan/src/data-types/mailstream_helper.c freeswitch/trunk/libs/libetpan/src/data-types/mailstream_helper.h freeswitch/trunk/libs/libetpan/src/data-types/mailstream_low.c freeswitch/trunk/libs/libetpan/src/data-types/mailstream_low.h freeswitch/trunk/libs/libetpan/src/data-types/mailstream_socket.c freeswitch/trunk/libs/libetpan/src/data-types/mailstream_socket.h freeswitch/trunk/libs/libetpan/src/data-types/mailstream_ssl.c freeswitch/trunk/libs/libetpan/src/data-types/mailstream_ssl.h freeswitch/trunk/libs/libetpan/src/data-types/mailstream_types.h freeswitch/trunk/libs/libetpan/src/data-types/mapping.c freeswitch/trunk/libs/libetpan/src/data-types/mapping.h freeswitch/trunk/libs/libetpan/src/data-types/md5.c freeswitch/trunk/libs/libetpan/src/data-types/md5.h freeswitch/trunk/libs/libetpan/src/data-types/md5global.h freeswitch/trunk/libs/libetpan/src/data-types/mmapstring.c freeswitch/trunk/libs/libetpan/src/data-types/mmapstring.h freeswitch/trunk/libs/libetpan/src/driver/ (props changed) freeswitch/trunk/libs/libetpan/src/driver/.cvsignore freeswitch/trunk/libs/libetpan/src/driver/Makefile freeswitch/trunk/libs/libetpan/src/driver/TODO freeswitch/trunk/libs/libetpan/src/driver/implementation/ (props changed) freeswitch/trunk/libs/libetpan/src/driver/implementation/.cvsignore freeswitch/trunk/libs/libetpan/src/driver/implementation/Makefile freeswitch/trunk/libs/libetpan/src/driver/implementation/data-message/ (props changed) freeswitch/trunk/libs/libetpan/src/driver/implementation/data-message/.cvsignore freeswitch/trunk/libs/libetpan/src/driver/implementation/data-message/Makefile freeswitch/trunk/libs/libetpan/src/driver/implementation/data-message/data_message_driver.c freeswitch/trunk/libs/libetpan/src/driver/implementation/data-message/data_message_driver.h freeswitch/trunk/libs/libetpan/src/driver/implementation/db/ (props changed) freeswitch/trunk/libs/libetpan/src/driver/implementation/db/.cvsignore freeswitch/trunk/libs/libetpan/src/driver/implementation/db/Makefile freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbdriver.c freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbdriver.h freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbdriver_message.c freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbdriver_message.h freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbdriver_types.h freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbstorage.c freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbstorage.h freeswitch/trunk/libs/libetpan/src/driver/implementation/hotmail/ (props changed) freeswitch/trunk/libs/libetpan/src/driver/implementation/hotmail/.cvsignore freeswitch/trunk/libs/libetpan/src/driver/implementation/hotmail/Makefile freeswitch/trunk/libs/libetpan/src/driver/implementation/hotmail/hotmailstorage.c freeswitch/trunk/libs/libetpan/src/driver/implementation/hotmail/hotmailstorage.h freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/ (props changed) freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/.cvsignore freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/Makefile freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver.c freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver.h freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_cached.c freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_cached.h freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_cached_message.c freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_cached_message.h freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_message.c freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_message.h freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_tools.c freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_tools.h freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_types.h freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapstorage.c freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapstorage.h freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/ (props changed) freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/.cvsignore freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/Makefile freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver.c freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver.h freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_cached.c freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_cached.h freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.c freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.h freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_message.c freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_message.h freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_tools.c freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_tools.h freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_types.h freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirstorage.c freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirstorage.h freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/ (props changed) freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/.cvsignore freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/Makefile freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver.c freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver.h freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_cached.c freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_cached.h freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.h freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_message.c freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_message.h freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_tools.h freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_types.h freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxstorage.c freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxstorage.h freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/ (props changed) freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/.cvsignore freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/Makefile freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver.c freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver.h freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_cached.c freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_cached.h freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_cached_message.c freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_cached_message.h freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_message.c freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_message.h freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_tools.c freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_tools.h freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_types.h freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhstorage.c freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhstorage.h freeswitch/trunk/libs/libetpan/src/driver/implementation/mime-message/ (props changed) freeswitch/trunk/libs/libetpan/src/driver/implementation/mime-message/.cvsignore freeswitch/trunk/libs/libetpan/src/driver/implementation/mime-message/Makefile freeswitch/trunk/libs/libetpan/src/driver/implementation/mime-message/mime_message_driver.c freeswitch/trunk/libs/libetpan/src/driver/implementation/mime-message/mime_message_driver.h freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/ (props changed) freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/.cvsignore freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/Makefile freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver.c freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver.h freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_cached.c freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_cached.h freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_message.c freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_message.h freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_tools.h freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_types.h freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpstorage.c freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpstorage.h freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/ (props changed) freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/.cvsignore freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/Makefile freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver.c freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver.h freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_cached.c freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_cached.h freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.h freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_message.c freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_message.h freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_tools.c freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_tools.h freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_types.h freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3storage.c freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3storage.h freeswitch/trunk/libs/libetpan/src/driver/interface/ (props changed) freeswitch/trunk/libs/libetpan/src/driver/interface/.cvsignore freeswitch/trunk/libs/libetpan/src/driver/interface/Makefile freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver.c freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver.h freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_errors.h freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_tools.c freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_tools.h freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_types.c freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_types.h freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_types_helper.c freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_types_helper.h freeswitch/trunk/libs/libetpan/src/driver/interface/mailfolder.c freeswitch/trunk/libs/libetpan/src/driver/interface/mailfolder.h freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage.c freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage.h freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage_tools.c freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage_tools.h freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage_types.c freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage_types.h freeswitch/trunk/libs/libetpan/src/driver/interface/mailstorage.c freeswitch/trunk/libs/libetpan/src/driver/interface/mailstorage.h freeswitch/trunk/libs/libetpan/src/driver/interface/mailstorage_tools.c freeswitch/trunk/libs/libetpan/src/driver/interface/mailstorage_tools.h freeswitch/trunk/libs/libetpan/src/driver/interface/mailstorage_types.h freeswitch/trunk/libs/libetpan/src/driver/tools/ (props changed) freeswitch/trunk/libs/libetpan/src/driver/tools/.cvsignore freeswitch/trunk/libs/libetpan/src/driver/tools/Makefile freeswitch/trunk/libs/libetpan/src/driver/tools/generic_cache.c freeswitch/trunk/libs/libetpan/src/driver/tools/generic_cache.h freeswitch/trunk/libs/libetpan/src/driver/tools/generic_cache_types.h freeswitch/trunk/libs/libetpan/src/driver/tools/imfcache.c freeswitch/trunk/libs/libetpan/src/driver/tools/imfcache.h freeswitch/trunk/libs/libetpan/src/driver/tools/mailthread.c freeswitch/trunk/libs/libetpan/src/driver/tools/mailthread.h freeswitch/trunk/libs/libetpan/src/driver/tools/mailthread_types.c freeswitch/trunk/libs/libetpan/src/driver/tools/mailthread_types.h freeswitch/trunk/libs/libetpan/src/engine/ (props changed) freeswitch/trunk/libs/libetpan/src/engine/.cvsignore freeswitch/trunk/libs/libetpan/src/engine/Makefile freeswitch/trunk/libs/libetpan/src/engine/mailengine.c freeswitch/trunk/libs/libetpan/src/engine/mailengine.h freeswitch/trunk/libs/libetpan/src/engine/mailprivacy.c freeswitch/trunk/libs/libetpan/src/engine/mailprivacy.h freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_gnupg.c freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_gnupg.h freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_smime.c freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_smime.h freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_tools.c freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_tools.h freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_types.h freeswitch/trunk/libs/libetpan/src/low-level/ (props changed) freeswitch/trunk/libs/libetpan/src/low-level/.cvsignore freeswitch/trunk/libs/libetpan/src/low-level/Makefile freeswitch/trunk/libs/libetpan/src/low-level/imap/ (props changed) freeswitch/trunk/libs/libetpan/src/low-level/imap/.cvsignore freeswitch/trunk/libs/libetpan/src/low-level/imap/Makefile freeswitch/trunk/libs/libetpan/src/low-level/imap/TODO freeswitch/trunk/libs/libetpan/src/low-level/imap/acl.c freeswitch/trunk/libs/libetpan/src/low-level/imap/acl.h freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_parser.c freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_parser.h freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_sender.c freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_sender.h freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_types.c freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_types.h freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore.c freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore.h freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_parser.c freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_parser.h freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_sender.c freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_sender.h freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_types.c freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_types.h freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap.c freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap.h freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_extension.c freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_extension.h freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_extension_types.h freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_helper.c freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_helper.h freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_keywords.c freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_keywords.h freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_parser.c freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_parser.h freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_print.c freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_print.h freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_sender.c freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_sender.h freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_socket.c freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_socket.h freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_ssl.c freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_ssl.h freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_types.c freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_types.h freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_types_helper.c freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_types_helper.h freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus.c freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus.h freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_parser.c freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_parser.h freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_sender.c freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_sender.h freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_types.c freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_types.h freeswitch/trunk/libs/libetpan/src/low-level/imf/ (props changed) freeswitch/trunk/libs/libetpan/src/low-level/imf/.cvsignore freeswitch/trunk/libs/libetpan/src/low-level/imf/Makefile freeswitch/trunk/libs/libetpan/src/low-level/imf/TODO freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf.c freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf.h freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_types.c freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_types.h freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_types_helper.c freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_types_helper.h freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write.c freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write.h freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_file.c freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_file.h freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_generic.c freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_generic.h freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_mem.c freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_mem.h freeswitch/trunk/libs/libetpan/src/low-level/maildir/ (props changed) freeswitch/trunk/libs/libetpan/src/low-level/maildir/.cvsignore freeswitch/trunk/libs/libetpan/src/low-level/maildir/Makefile freeswitch/trunk/libs/libetpan/src/low-level/maildir/maildir.c freeswitch/trunk/libs/libetpan/src/low-level/maildir/maildir.h freeswitch/trunk/libs/libetpan/src/low-level/maildir/maildir_types.h freeswitch/trunk/libs/libetpan/src/low-level/mbox/ (props changed) freeswitch/trunk/libs/libetpan/src/low-level/mbox/.cvsignore freeswitch/trunk/libs/libetpan/src/low-level/mbox/Makefile freeswitch/trunk/libs/libetpan/src/low-level/mbox/TODO freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox.c freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox.h freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox_parse.c freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox_parse.h freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox_types.c freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox_types.h freeswitch/trunk/libs/libetpan/src/low-level/mh/ (props changed) freeswitch/trunk/libs/libetpan/src/low-level/mh/.cvsignore freeswitch/trunk/libs/libetpan/src/low-level/mh/Makefile freeswitch/trunk/libs/libetpan/src/low-level/mh/mailmh.c freeswitch/trunk/libs/libetpan/src/low-level/mh/mailmh.h freeswitch/trunk/libs/libetpan/src/low-level/mime/ (props changed) freeswitch/trunk/libs/libetpan/src/low-level/mime/.cvsignore freeswitch/trunk/libs/libetpan/src/low-level/mime/Makefile freeswitch/trunk/libs/libetpan/src/low-level/mime/TODO freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime.c freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime.h freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_content.c freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_content.h freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_decode.c freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_decode.h freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_disposition.c freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_disposition.h freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_types.c freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_types.h freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_types_helper.c freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_types_helper.h freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write.c freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write.h freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_file.c freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_file.h freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_generic.c freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_generic.h freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_mem.c freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_mem.h freeswitch/trunk/libs/libetpan/src/low-level/nntp/ (props changed) freeswitch/trunk/libs/libetpan/src/low-level/nntp/.cvsignore freeswitch/trunk/libs/libetpan/src/low-level/nntp/Makefile freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp.c freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp.h freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp_socket.c freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp_socket.h freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp_ssl.c freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp_ssl.h freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp_types.h freeswitch/trunk/libs/libetpan/src/low-level/pop3/ (props changed) freeswitch/trunk/libs/libetpan/src/low-level/pop3/.cvsignore freeswitch/trunk/libs/libetpan/src/low-level/pop3/Makefile freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3.c freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3.h freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_helper.c freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_helper.h freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_socket.c freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_socket.h freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_ssl.c freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_ssl.h freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_types.h freeswitch/trunk/libs/libetpan/src/low-level/smtp/ (props changed) freeswitch/trunk/libs/libetpan/src/low-level/smtp/.cvsignore freeswitch/trunk/libs/libetpan/src/low-level/smtp/Makefile freeswitch/trunk/libs/libetpan/src/low-level/smtp/TODO freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp.c freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp.h freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_helper.c freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_helper.h freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_socket.c freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_socket.h freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_ssl.c freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_ssl.h freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_types.h freeswitch/trunk/libs/libetpan/src/main/ (props changed) freeswitch/trunk/libs/libetpan/src/main/.cvsignore freeswitch/trunk/libs/libetpan/src/main/Makefile freeswitch/trunk/libs/libetpan/src/main/libetpan.h freeswitch/trunk/libs/libetpan/src/main/libetpan_version.c freeswitch/trunk/libs/libetpan/src/main/libetpan_version.h.in freeswitch/trunk/libs/libetpan/src/windows/ freeswitch/trunk/libs/libetpan/src/windows/dirent.c freeswitch/trunk/libs/libetpan/src/windows/misc.c freeswitch/trunk/libs/libetpan/src/windows/mmap.c freeswitch/trunk/libs/libetpan/src/windows/time_r.c freeswitch/trunk/libs/libetpan/src/windows/win_etpan.h freeswitch/trunk/libs/libetpan/src/windows/wsocket.cpp freeswitch/trunk/libs/libetpan/tests/ freeswitch/trunk/libs/libetpan/tests/Makefile freeswitch/trunk/libs/libetpan/tests/README freeswitch/trunk/libs/libetpan/tests/compose-msg.c freeswitch/trunk/libs/libetpan/tests/decrypt.c freeswitch/trunk/libs/libetpan/tests/fetch-attachment.c freeswitch/trunk/libs/libetpan/tests/frm-common.c freeswitch/trunk/libs/libetpan/tests/frm-common.h freeswitch/trunk/libs/libetpan/tests/frm-simple.c freeswitch/trunk/libs/libetpan/tests/frm-tree.c freeswitch/trunk/libs/libetpan/tests/frm.c freeswitch/trunk/libs/libetpan/tests/option-parser.c freeswitch/trunk/libs/libetpan/tests/option-parser.h freeswitch/trunk/libs/libetpan/tests/pgp.c freeswitch/trunk/libs/libetpan/tests/readmsg-common.c freeswitch/trunk/libs/libetpan/tests/readmsg-common.h freeswitch/trunk/libs/libetpan/tests/readmsg-simple.c freeswitch/trunk/libs/libetpan/tests/readmsg-uid.c freeswitch/trunk/libs/libetpan/tests/readmsg.c freeswitch/trunk/libs/libetpan/tests/smime.c freeswitch/trunk/libs/libetpan/tests/smtpsend.c Log: add libetpan 0.48 to in tree libs Added: freeswitch/trunk/libs/libetpan/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,16 @@ +aclocal.m4 +autom4te.cache +config.guess +config.h +config.h.in +config.log +config.status +config.sub +configure +include +libetpan-config +libetpan-config.h +libtool +ltmain.sh +Makefile +Rules Added: freeswitch/trunk/libs/libetpan/COPYRIGHT ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/COPYRIGHT Wed Dec 20 15:28:56 2006 @@ -0,0 +1,31 @@ +libEtPan! -- a mail stuff library + +Copyright (C) 2001 - 2005 - DINH Viet Hoa +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the libEtPan! project nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +This project contains code from sendmail, NetBSD, +RSA Data Security MD5 Message-Digest Algorithm, Cyrus IMAP. Added: freeswitch/trunk/libs/libetpan/ChangeLog ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/ChangeLog Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3176 @@ +2006-10-26 - libetpan-0.47 - alfie + + * release 0.47 - Hypergeek + feature enhancements: + UIDPLUS implemented + fixes: + various smaller code fixes + +2006-10-26 - libetpan-0.47cvs6 - hoa + + * src/low-level/imap/mailimap_types.c + fixed the code of response_info_free(). + +2006-10-25 - libetpan-0.47cvs5 - hoa + + * src/driver/implementation/db/dbdriver.c + fixed the code of db_get_next_validity(). + +2006-10-22 - libetpan-0.47cvs4 - hoa + + * src/low-level/imf/mailimf_types_helper.c + fixed handling of Bcc. + +2006-10-20 - libetpan-0.47cvs3 - hoa + + * src/low-level/imap/uidplus.h + fixed extern declaration. + +2006-10-20 - libetpan-0.47cvs2 - hoa + + * src/low-level/imap/acl.[ch] + * src/low-level/imap/annotatemore.[ch] + * src/low-level/imap/mailimap_extension.[ch] + * src/low-level/imap/uidplus.[ch] + added an API to check the capabilities. + fixed UIDPLUS copy. + +2006-10-20 - libetpan-0.47cvs1 - hoa + + * configure.in + * src/low-level/imap/Makefile + * src/low-level/imap/acl.[ch] + * src/low-level/imap/acl_types.c + * src/low-level/imap/annotatemore.[ch] + * src/low-level/imap/annotatemore_types.c + * src/low-level/imap/mailimap.[ch] + * src/low-level/imap/mailimap_extension.c + * src/low-level/imap/mailimap_extension_types.h + * src/low-level/imap/mailimap_parser.[ch] + * src/low-level/imap/mailimap_sender.[ch] + * src/low-level/imap/mailimap_types.[ch] + Fixed API of extension. Exported some functions. + + * src/low-level/imap/uidplus.[ch] ** NEW FILES ** + * src/low-level/imap/uidplus_parser.[ch] ** NEW FILES ** + * src/low-level/imap/uidplus_sender.[ch] ** NEW FILES ** + * src/low-level/imap/uidplus_types.[ch] ** NEW FILES ** + implementation of UIDPLUS. + +2006-10-13 - libetpan-0.47 - alfie + + * release 0.47 - Son Et Lumiere + feature enhancements: + IPv6 Support + fixes: + various leaks and crashes + MIME decoding fix + gnutls fix + SASL fix + AUTH parser fix + +2006-10-13 - libetpan-0.46cvs13 - alfie + + * src/low-level/smtp/mailsmtp_types.h + order it backward compatible. + +2006-10-12 - libetpan-0.46cvs12 - hoa + + * src/low-level/imap/mailimap.c + fixed crash. + +2006-10-12 - libetpan-0.46cvs11 - hoa + + * src/low-level/maildir/maildir.c + fixed memory leaks. + +2006-10-07 - libetpan-0.46cvs10 - hoa + + * src/low-level/mime/mailmime_decode.c + fixed MIME header decoding. + +2006-09-25 - libetpan-0.46cvs9 - colin + + * src/data-types/mailstream_ssl.c + Really fix gnutls' init. + +2006-09-24 - libetpan-0.46cvs8 - colin + + * src/data-types/mailstream_ssl.c + Fix a typo that made gnutls crash on some servers + (mail.hp.com:993 for example). Sorry :-/ + +2006-09-05 - libetpan-0.46cvs7 - hoa + + * src/low-level/imap/mailimap_parser.c + implemented workaround for Binc IMAP. + FLAGS response can be sent with "\*" on Binc IMAP. + That's not conformant to IMAP RFC. + +2006-08-30 - libetpan-0.46cvs6 - hoa + + * src/engine/mailprivacy_smime.c + improved performance of certificates collector. + + * src/low-level/imap/mailimap.c + * src/low-level/pop3/mailpop3.c + * src/low-level/smtp/mailsmtp.c + fixed use of SASL. + Thanks to Andrei N. Balabohin. + +2006-08-05 - libetpan-0.46cvs5 - hoa + + * src/data-types/Makefile + * src/data-types/maillock.c + * src/main/libetpan.h + exports maillock.h + file descriptor is now optional. + + * src/data-types/mailstream_ssl.c + disable fcntl() call on win32. + + * src/driver/implementation/imap/imapdriver_cached.c + fixed a leak. + + * src/driver/implementation/nntp/nntpdriver_tools.c + fixed error code. + + * src/low-level/imf/mailimf.c + fixed a leak. + + * src/low-level/mime/mailmime_decode.c + 'unknown' character set is considered as 'iso-8859-1'. + + * src/low-level/pop3/mailpop3.c + fixed AUTH parser. + Thanks to Andrei N. Balabohin. + + * src/low-level/smtp/mailsmtp.c + * src/low-level/smtp/mailsmtp_types.h + improved error management. + Thanks to Andrei N. Balabohin. + +2006-07-15 - libetpan-0.46cvs4 - hoa + + * configure.in + IPv6 is enabled by default. + +2006-07-15 - libetpan-0.46cvs3 - hoa + + * configure.in + * src/data-types/connect.c + * src/driver/interface/mailstorage_tools.c + IPv6 implementation. Thanks to Didier Barvaux. + +2006-07-15 - libetpan-0.46cvs2 - hoa + + * build-windows/libetpan_version.h + fixed libetpan version for Windows. + + * src/driver/implementation/imap/imapdriver_cached.c + fixed function prototype. + +2006-07-14 - libetpan-0.46cvs1 - hoa + + * src/low-level/imf/mailimf.c + fixed a crash in case of parse error on Bcc field. + +2006-07-12 - libetpan-0.46 - alfie + + * release 0.46 - Drawing Circles + feature enhancements: + imap extension api + imap annotate + C89 conformance + fixes: + fixed crash when using gnutls + various other (small) fixes + +2006-07-03 - libetpan-0.45cvs17 - skunk + + * Rules.in + new "prepare" rule to prevent redundant header copying + * install-sh + updated to latest version from autoconf-2.60 package + * src/data-types/charconv.c + moved variable declarations up to avoid having declarations + after statements, plus some minor syntax fixes + +2006-06-29 - libetpan-0.45cvs16 - hoa + + * configure.in + temporary fix for install. + +2006-06-28 - libetpan-0.45cvs15 - skunk + + * src/data-types/mailstream.c + * src/driver/implementation/maildir/maildirdriver.c + * src/driver/implementation/pop3/pop3driver.c + checked in the remaining bits of the last patch + +2006-06-26 - libetpan-0.45cvs14 - hoa + + * Rules.in + * configure.in + * build-windows/libetpan_version.h + * src/Makefile.in + * src/data-types/charconv.c + * src/data-types/mailstream_socket.c + * src/data-types/mailstream_ssl.c + * src/data-types/mapping.c + * src/data-types/mmapstring.c + * src/driver/Makefile + * src/driver/implementation/Makefile + * src/driver/implementation/data-message/Makefile + * src/driver/implementation/data-message/data_message_driver.c + * src/driver/implementation/db/Makefile + * src/driver/implementation/db/dbdriver.c + * src/driver/implementation/db/dbdriver_message.c + * src/driver/implementation/db/dbstorage.c + * src/driver/implementation/hotmail/Makefile + * src/driver/implementation/imap/Makefile + * src/driver/implementation/imap/imapdriver.c + * src/driver/implementation/imap/imapdriver_cached.c + * src/driver/implementation/imap/imapdriver_cached_message.c + * src/driver/implementation/imap/imapdriver_message.c + * src/driver/implementation/imap/imapstorage.c + * src/driver/implementation/maildir/Makefile + * src/driver/implementation/maildir/maildirdriver_cached.c + * src/driver/implementation/maildir/maildirdriver_cached_message.c + * src/driver/implementation/maildir/maildirdriver_message.c + * src/driver/implementation/maildir/maildirstorage.c + * src/driver/implementation/mbox/Makefile + * src/driver/implementation/mbox/mboxdriver.c + * src/driver/implementation/mbox/mboxdriver_cached.c + * src/driver/implementation/mbox/mboxdriver_cached_message.c + * src/driver/implementation/mbox/mboxdriver_message.c + * src/driver/implementation/mbox/mboxstorage.c + * src/driver/implementation/mh/Makefile + * src/driver/implementation/mh/mhdriver.c + * src/driver/implementation/mh/mhdriver_cached.c + * src/driver/implementation/mh/mhdriver_cached_message.c + * src/driver/implementation/mh/mhdriver_message.c + * src/driver/implementation/mh/mhdriver_tools.c + * src/driver/implementation/mh/mhstorage.c + * src/driver/implementation/mime-message/Makefile + * src/driver/implementation/mime-message/mime_message_driver.c + * src/driver/implementation/nntp/Makefile + * src/driver/implementation/nntp/nntpdriver.c + * src/driver/implementation/nntp/nntpdriver_cached.c + * src/driver/implementation/nntp/nntpdriver_cached_message.c + * src/driver/implementation/nntp/nntpdriver_message.c + * src/driver/implementation/nntp/nntpstorage.c + * src/driver/implementation/pop3/Makefile + * src/driver/implementation/pop3/pop3driver_cached.c + * src/driver/implementation/pop3/pop3driver_cached_message.c + * src/driver/implementation/pop3/pop3driver_message.c + * src/driver/implementation/pop3/pop3storage.c + * src/driver/interface/Makefile + * src/driver/interface/maildriver_types.h + * src/driver/tools/Makefile + * src/driver/tools/generic_cache.c + * src/engine/Makefile + * src/engine/mailprivacy_gnupg.c + * src/engine/mailprivacy_smime.c + * src/engine/mailprivacy_tools.c + * src/low-level/Makefile + * src/low-level/imap/Makefile + * src/low-level/imap/acl.c + * src/low-level/imap/acl_parser.c + * src/low-level/imap/acl_sender.c + * src/low-level/imap/acl_types.c + * src/low-level/imap/annotatemore.c + * src/low-level/imap/annotatemore_parser.c + * src/low-level/imap/annotatemore_sender.c + * src/low-level/imap/annotatemore_types.c + * src/low-level/imap/mailimap_extension.c + * src/low-level/imap/mailimap_helper.c + * src/low-level/imap/mailimap_keywords.c + * src/low-level/imap/mailimap_socket.c + * src/low-level/imap/mailimap_ssl.c + * src/low-level/imap/mailimap_types.c + * src/low-level/imap/mailimap_types_helper.c + * src/low-level/maildir/maildir.c + * src/low-level/mbox/mailmbox.c + * src/low-level/mh/mailmh.c + * src/low-level/mime/mailmime.c + * src/low-level/mime/mailmime_decode.c + * src/low-level/mime/mailmime_disposition.c + * src/low-level/mime/mailmime_types.c + * src/low-level/mime/mailmime_types_helper.c + * src/low-level/mime/mailmime_write.c + * src/low-level/mime/mailmime_write_file.c + * src/low-level/mime/mailmime_write_generic.c + * src/low-level/mime/mailmime_write_mem.c + * src/low-level/nntp/newsnntp.c + * src/low-level/nntp/newsnntp_socket.c + * src/low-level/nntp/newsnntp_ssl.c + * src/low-level/smtp/mailsmtp_helper.c + * src/low-level/smtp/mailsmtp_socket.c + * src/low-level/smtp/mailsmtp_ssl.c + * tests/readmsg-common.c + conformance patch by Daniel Richard G. + +2006-06-16 - libetpan-0.45cvs13 - smarinier + + * src/data-types/charconv.[ch] + extended_charconv might be used if you don't have iconv + or if you want to handle some conversions by yourself + + * src//driver/interface/maildriver_types.[ch] + libetpan_malloc and libetpan_freei should be used to + allocate/free data freed/allocated by libetpan + +2006-06-07 - libetpan-0.45cvs12 - smarinier + + * src/driver/implementation/imap/imapdriver.c + * src/driver/implementation/imap/imapdriver_cached.c + * src/driver/implementation/maildir/maildirdriver.c + * src/driver/implementation/maildir/maildirdriver_cached.c + * src/driver/implementation/mbox/mboxdriver.c + * src/driver/implementation/mbox/mboxdriver_cached.c + * src/driver/implementation/mh/mhdriver.c + * src/driver/implementation/mh/mhdriver_cached.c + * src/driver/implementation/nntp/nntpdriver.c + * src/driver/implementation/nntp/nntpdriver_cached.c + * src/driver/implementation/nntp/nntpdriver_tools.[ch] + * src/driver/implementation/pop3/pop3driver.c + * src/driver/implementation/pop3/pop3driver_cached.c + * src/driver/interface/maildriver.[ch] + * src/driver/interface/maildriver_tools.[ch] + * src/driver/interface/maildriver_types.h + * src/low-level/imap/mailimap_helper.[ch] + * src/low-level/mime/mailmime_write_mem.c + * src/low-level/pop3/mailpop3_helper.[ch] + * tests/option-parser.[ch] + use const char* when char* is not necessary (2) + +2006-06-06 - libetpan-0.45cvs11 - smarinier + + * src/driver/implementation/imap/imapdriver.c + add (slow) remove_message to imap_driver + +2006-06-02 - libetpan-0.45cvs10 - smarinier + + * src/driver/implementation/nntp/nntpstorage.c + minor bug on nn_command deletion + + * src/driver/implementation/imap/imapstorage.[ch] + * src/driver/implementation/maildir/maildirstorage.[ch] + * src/driver/implementation/nntp/nntpstorage.[ch] + * src/driver/interface/mailstorage.[ch] + * src/data-types/md5.[ch] + * src/data-types/md5global.h + * src/driver/implementation/mbox/mboxstorage.[ch] + * src/driver/implementation/mh/mhstorage.[ch] + * src/driver/implementation/pop3/pop3storage.[ch] + use const char* when char* is not necessary + +2006-06-02 - libetpan-0.45cvs9 - hoa + + * src/driver/interface/maildriver.c + fixed copy-paste bug. Thanks to Sebastien Marinier. + +2006-05-30 - libetpan-0.45cvs8 - hoa + + * configure.in + support for newer version of Debian Berkeley DB. + +2006-05-22 - libetpan-0.45cvs7 - hoa + + * autogen.sh + * configure.in + * src/data-types/carray.c + * src/data-types/charconv.[ch] + * src/data-types/chash.c + * src/data-types/cinthash.c + * src/data-types/clist.[ch] + * src/data-types/connect.[ch] + * src/data-types/mail_cache_db.c + * src/data-types/maillock.c + * src/data-types/mailsasl.c + * src/data-types/mailsem.c + * src/data-types/mailstream_helper.c + * src/data-types/mailstream_low.c + * src/data-types/mailstream_socket.c + * src/data-types/mailstream_ssl.c + * src/data-types/md5.h + * src/data-types/md5global.h + * src/data-types/mmapstring.c + * src/driver/implementation/data-message/data_message_driver.c + * src/driver/implementation/db/dbdriver.c + * src/driver/implementation/db/dbdriver_message.c + * src/driver/implementation/db/dbstorage.c + * src/driver/implementation/hotmail/hotmailstorage.c + * src/driver/implementation/imap/imapdriver.c + * src/driver/implementation/imap/imapdriver_cached.c + * src/driver/implementation/imap/imapdriver_cached_message.c + * src/driver/implementation/imap/imapdriver_message.c + * src/driver/implementation/imap/imapdriver_tools.c + * src/driver/implementation/imap/imapdriver_types.h + * src/driver/implementation/imap/imapstorage.c + * src/driver/implementation/maildir/maildirdriver.c + * src/driver/implementation/maildir/maildirdriver_cached.c + * src/driver/implementation/maildir/maildirdriver_cached_message.c + * src/driver/implementation/maildir/maildirdriver_message.c + * src/driver/implementation/maildir/maildirdriver_tools.c + * src/driver/implementation/maildir/maildirdriver_types.h + * src/driver/implementation/maildir/maildirstorage.c + * src/driver/implementation/mbox/mboxdriver.c + * src/driver/implementation/mbox/mboxdriver_cached.c + * src/driver/implementation/mbox/mboxdriver_cached_message.c + * src/driver/implementation/mbox/mboxdriver_message.c + * src/driver/implementation/mbox/mboxdriver_tools.c + * src/driver/implementation/mbox/mboxdriver_types.h + * src/driver/implementation/mbox/mboxstorage.c + * src/driver/implementation/mh/mhdriver.c + * src/driver/implementation/mh/mhdriver_cached.c + * src/driver/implementation/mh/mhdriver_cached_message.c + * src/driver/implementation/mh/mhdriver_message.c + * src/driver/implementation/mh/mhdriver_tools.c + * src/driver/implementation/mh/mhdriver_types.h + * src/driver/implementation/mh/mhstorage.c + * src/driver/implementation/mime-message/mime_message_driver.c + * src/driver/implementation/nntp/nntpdriver.c + * src/driver/implementation/nntp/nntpdriver_cached.c + * src/driver/implementation/nntp/nntpdriver_cached_message.c + * src/driver/implementation/nntp/nntpdriver_message.c + * src/driver/implementation/nntp/nntpdriver_tools.c + * src/driver/implementation/nntp/nntpdriver_types.h + * src/driver/implementation/nntp/nntpstorage.c + * src/driver/implementation/pop3/pop3driver.c + * src/driver/implementation/pop3/pop3driver_cached.c + * src/driver/implementation/pop3/pop3driver_cached_message.c + * src/driver/implementation/pop3/pop3driver_message.c + * src/driver/implementation/pop3/pop3driver_tools.c + * src/driver/implementation/pop3/pop3driver_types.h + * src/driver/implementation/pop3/pop3storage.c + * src/driver/interface/maildriver.c + * src/driver/interface/maildriver_errors.h + * src/driver/interface/maildriver_tools.c + * src/driver/interface/maildriver_types.[ch] + * src/driver/interface/maildriver_types_helper.c + * src/driver/interface/mailfolder.c + * src/driver/interface/mailmessage.c + * src/driver/interface/mailmessage_tools.[ch] + * src/driver/interface/mailmessage_types.[ch] + * src/driver/interface/mailstorage.c + * src/driver/tools/generic_cache.c + * src/driver/tools/imfcache.c + * src/driver/tools/mailthread.c + * src/driver/tools/mailthread_types.[ch] + * src/engine/mailengine.c + * src/engine/mailprivacy.c + * src/engine/mailprivacy_gnupg.c + * src/engine/mailprivacy_smime.c + * src/engine/mailprivacy_tools.c + * src/low-level/imap/mailimap.c + * src/low-level/imap/mailimap_parser.c + * src/low-level/imap/mailimap_sender.c + * src/low-level/imap/mailimap_socket.[ch] + * src/low-level/imap/mailimap_ssl.[ch] + * src/low-level/imap/mailimap_types.h + * src/low-level/imf/mailimf.c + * src/low-level/imf/mailimf.h + * src/low-level/imf/mailimf_types.h + * src/low-level/imf/mailimf_types_helper.[ch] + * src/low-level/imf/mailimf_write_generic.c + * src/low-level/maildir/maildir.c + * src/low-level/maildir/maildir_types.h + * src/low-level/mbox/mailmbox.c + * src/low-level/mbox/mailmbox_parse.c + * src/low-level/mbox/mailmbox_types.[ch] + * src/low-level/mh/mailmh.[ch] + * src/low-level/mime/mailmime_content.c + * src/low-level/mime/mailmime_decode.c + * src/low-level/mime/mailmime_types.h + * src/low-level/mime/mailmime_types_helper.c + * src/low-level/mime/mailmime_write_file.c + * src/low-level/mime/mailmime_write_generic.c + * src/low-level/mime/mailmime_write_mem.c + * src/low-level/nntp/newsnntp.h + * src/low-level/nntp/newsnntp_socket.[ch] + * src/low-level/nntp/newsnntp_ssl.[ch] + * src/low-level/nntp/newsnntp_types.h + * src/low-level/pop3/mailpop3.c + * src/low-level/pop3/mailpop3_helper.c + * src/low-level/pop3/mailpop3_socket.[ch] + * src/low-level/pop3/mailpop3_ssl.[ch] + * src/low-level/pop3/mailpop3_types.h + * src/low-level/smtp/mailsmtp.c + * src/low-level/smtp/mailsmtp_helper.[ch] + * src/low-level/smtp/mailsmtp_socket.c + * src/low-level/smtp/mailsmtp_ssl.[ch] + * src/low-level/smtp/mailsmtp_types.h + * src/main/libetpan_version.c + * tests/readmsg.c + cleanup of libetpan. + Thanks to Daniel Richard G. + +2006-05-17 - libetpan-0.45cvs6 - hoa + + * src/data-types/charconv.c + fixed UTF-8 character maximum size. + + * src/driver/implementation/imap/imapdriver_cached.c + * src/driver/implementation/imap/imapdriver_types.h + message list cache. + + * src/driver/implementation/mh/mhdriver_tools.c + fixed 'From ' skipper. + +2006-04-16 - libetpan-0.45cvs5 - colin + + * src/low-level/imap/annotatemore_types.c + Fix missing mailimap_annotatemore_entry_list_new + +2006-04-16 - libetpan-0.45cvs4 - colin + + * src/data-types/mailstream_ssl.c + Fix crash on closed connection with gnutls (and make sure + it won't happen with openssl), by returning -1 instead of + GNUTLS_ERROR_*: mailstream_read() error return value is -1 + everywhere in mailstream.c + Fixes debian bugs: 356325, 358882, maybe 362747 + +2006-04-15 - libetpan-0.45cvs3 - hoa + + * src/low-level/imap/annotatemore_parser.c + * src/low-level/imap/annotatemore_types.c + * src/low-level/imap/annotatemore_types.h + prefixed defines + +2006-04-15 - libetpan-0.45cvs2 - hoa + + * src/low-level/imap/annotatemore.[ch] * NEW FILES * + * src/low-level/imap/annotatemore_parser.[ch] * NEW FILES * + * src/low-level/imap/annotatemore_sender.[ch] * NEW FILES * + * src/low-level/imap/annotatemore_types.[ch] * NEW FILES * + * src/low-level/imap/mailimap_extension.[ch] * NEW FILES * + * src/low-level/imap/mailimap_extension_types.h * NEW FILE * + * src/low-level/imap/Makefile + * src/low-level/imap/mailimap.[ch] + * src/low-level/imap/mailimap_parser.[ch] + * src/low-level/imap/mailimap_sender.[ch] + * src/low-level/imap/mailimap_socket.[ch] + * src/low-level/imap/mailimap_types.[ch] + implemented ANNOTATE extension. + more flexible interface to add IMAP extensions. + Thanks to Michael Leupold. + +2006-04-07 - libetpan-0.45cvs1 - hoa + + * src/driver/interface/mailfolder.[ch] + export properly functions. + + * src/data-types/connect.c + * src/low-level/imap/mailimap_socket.c + * src/low-level/nntp/newsnntp_socket.c + * src/low-level/pop3/mailpop3_socket.c + * src/low-level/smtp/mailsmtp_socket.c + fixed autolookup of port numbers. + +2006-03-22 - libetpan-0.45 + + * release 0.45 - Depth Charge + bugfix release + +2006-03-22 - libetpan-0.44cvs2 - hoa + + * src/data-types/carray.h + * src/data-types/charconv.h + * src/data-types/chash.h + * src/data-types/mailstream_types.h + * src/data-types/mmapstring.h + * src/low-level/mime/mailmime_types.h + fixed includes + +2006-03-20 - libetpan-0.44cvs1 - hoa + + * src/data-types/carray.h + * src/data-types/charconv.h + * src/data-types/chash.h + * src/data-types/mailstream_types.h + * src/data-types/mmapstring.h + * src/low-level/mime/mailmime_types.h + fixed includes + +2006-03-10 - libetpan-0.44 + + * release 0.44 - Lateralus + bugfix release + fixed versions + +2006-03-08 - libetpan-0.43 + + * release 0.43 - Lateralus + bugfix release + +2006-03-08 - libetpan-0.42cvs5 - hoa + + * ChangeLog + * libetpan-config.in + prepare for release + +2006-02-15 - libetpan-0.42cvs4 - colin + + * src/data-types/mailstream_ssl.c + * src/data-types/mailstream_ssl.h + Implement certificate retrieval + +2006-02-15 - libetpan-0.42cvs3 - colin + + * src/data-types/mailstream_ssl.c + * src/data-types/mailstream_ssl.h + * src/driver/implementation/imap/imapdriver.c + * src/driver/implementation/pop3/pop3driver.c + * src/low-level/smtp/mailsmtp_socket.c + After a bit of googling (and checking SC's sources too), it + seems that + - use SSLv23 for SSL connections + - use TLSv1 for STARTTLS connections + is the way to go. + + This patch implements a new mailstream_low_tls_open() to + complement mailstream_low_ssl_open(), which allows caller + to use what it needs. + Tested with a few differents servers: + - STARTTLS works ok, SSL works ok with an openssl-libetpan + - STARTTLS works ok, SSL works ok with a gnutls-libetpan + - one server, the one mentioned in bug 911, doesn't get + TLSv1 at all, and insists on SSLv23 even with + STARTTLS, which I think is a server bug + + Finally, Gnutls must do stuff differently (more automagically) + than + openssl because there's no need to specify the protocol to use, + it just + works with SSL and STARTTLS. + + Updated drivers too. + +2006-02-14 - libetpan-0.42cvs2 - colin + + * src/data-types/mailstream_ssl.c + Use SSLv23 instead of TLSv1, seems to be more + universal + +2006-02-09 - libetpan-0.42cvs1 - colin + + * src/data-types/mailstream_ssl.c + Fix return value when we get SSL_ERROR_ZERO_RETURN + +2006-01-09 - libetpan-0.42 + + * release 0.41 - Figure Number Five + bugfix release + +2006-01-04 - libetpan-0.41cvs10 - hoa + + * autogen.sh + * configure.in + * src/Makefile.in + fixed build. + + * src/low-level/smtp/mailsmtp.c + fixed SMTP SASL login. + + * src/main/libetpan.h + added public API. + +2005-12-22 - libetpan-0.41cvs9 - hoa + + * src/engine/mailprivacy_tools.[ch] + fixed visibility of functions. + +2005-12-20 - libetpan-0.41cvs8 - hoa + + * src/low-level/maildir/maildir.c + fixed maildir expunge. + + * src/low-level/smtp/mailsmtp.[ch] + implemented SMTP RSET (reset). + +2005-12-18 - libetpan-0.41cvs7 - hoa + + * src/low-level/smtp/mailsmtp.[ch] + implemented SMTP NOOP. + +2005-12-16 - libetpan-0.41cvs6 - hoa + + * Makefile.in + added empty target 'test' + + * src/data-types/mailsem.c + * src/engine/mailengine.c + fixed build when disabling thread safety. + +2005-12-16 - libetpan-0.41cvs5 - hoa + + * src/engine/mailprivacy_tools.c + fixed quoting of filename in shell calls. + +2005-12-07 - libetpan-0.41cvs4 - hoa + + * src/data-types/mailstream_ssl.c + fixed build when SSL is not available. + +2005-12-07 - libetpan-0.41cvs3 - hoa + + * src/engine/mailprivacy_gnupg.c + * src/engine/mailprivacy_smime.c + fixed quoting of filename in shell calls. + +2005-12-04 - libetpan-0.41cvs2 - hoa + + * configure.in + fixed libtool version + +2005-12-02 - libetpan-0.41cvs1 - hoa + + * src/engine/mailengine.c + fixed crash. + +2005-12-02 - libetpan-0.41 + + * release 0.41 - Transfixion + passphrase is implemented for S/MIME and PGP. + avoid symbols conflict between GnuTLS and OpenSSL. + +2005-11-30 - libetpan-0.40cvs6 - hoa + + * src/engine/mailprivacy.c + * src/engine/mailprivacy_gnupg.c + * src/engine/mailprivacy_smime.c + * src/engine/mailprivacy_tools.[ch] + fixed signing. + + * tests/smime.c + display needed passphrase. + +2005-11-21 - libetpan-0.40cvs5 - hoa + + * configure.in + OpenSSL has priority in detection. + + * src/engine/mailprivacy.[ch] + * src/engine/mailprivacy_gnupg.[ch] + * src/engine/mailprivacy_smime.[ch] + * src/engine/mailprivacy_tools.[ch] + * src/engine/mailprivacy_types.h + implemented support of passphrase. + + * tests/Makefile + * tests/frm-common.c + * tests/frm-simple.c + * tests/frm-tree.c + fixed compilation of tests. + + * tests/pgp.c * NEW FILE * + * tests/smime.c * NEW FILE * + * tests/decrypt.c * NEW FILE * + some tests for S/MIME, PGP. + +2005-10-09 - libetpan-0.40cvs4 - colin + + * src/data-types/mailstream_ssl.c + Try to finish handshaking when + possible with gnutls. + +2005-10-09 - libetpan-0.40cvs3 - colin + + * src/data-types/mailstream_ssl.c + fixed deadlock on the mutex + +2005-10-09 - libetpan-0.40cvs2 - colin + + * src/data-types/mailstream_ssl.c + fixed compilation with GnuTLS + +2005-10-09 - libetpan-0.40cvs1 - hoa + + * configure.in + * src/data-types/mailstream_ssl.c + * src/data-types/mailstream_ssl.h + avoid symbols conflicts between OpenSSL and GnuTLS. + Thanks to Colin Leroy. + +2005-10-07 - libetpan-0.40 - hoa + + * release 0.40 - Kashmir + SSL initialization is optional. + +2005-10-06 - libetpan-0.39cvs2 - hoa + + * src/Makefile.in + * src/data-types/mailstream_socket.c + * src/data-types/mailstream_ssl.c + fixed compilation on Solaris. + +2005-10-02 - libetpan-0.39cvs1 - hoa + + * src/data-types/mailstream_low.c + * src/data-types/mailstream_ssl.[ch] + * src/low-level/imap/mailimap_ssl.c + * src/low-level/nntp/newsnntp_ssl.c + * src/low-level/pop3/mailpop3_ssl.c + * src/low-level/smtp/mailsmtp_ssl.c + * tests/frm.c + SSL initialization is optional + fixed SSL port + fixed warning in tests + +2005-09-16 - libetpan-0.39 - hoa + + * release 0.39 - Deliverance + compatibility with GnuTLS + SASL for higher level + +2005-09-12 - libetpan-0.38cvs5 - colin + + * src/data-types/mailstream_ssl.c + fixed compatibility with GnuTLS. + +2005-08-17 - libetpan-0.38cvs4 - hoa + + * src/engine/mailprivacy_smime.c + fixed crash when a S/MIME 2 signed message does not verify. + +2005-08-14 - libetpan-0.38cvs3 - hoa + + * src/driver/implementation/db/dbdriver.c + * src/driver/implementation/imap/imapdriver.c + * src/driver/implementation/imap/imapdriver_cached.c + * src/driver/implementation/imap/imapdriver_types.h + * src/driver/implementation/imap/imapstorage.c + * src/driver/implementation/imap/imapstorage.h + * src/driver/implementation/maildir/maildirdriver.c + * src/driver/implementation/maildir/maildirdriver_cached.c + * src/driver/implementation/mbox/mboxdriver.c + * src/driver/implementation/mbox/mboxdriver_cached.c + * src/driver/implementation/mh/mhdriver.c + * src/driver/implementation/mh/mhdriver_cached.c + * src/driver/implementation/nntp/nntpdriver.c + * src/driver/implementation/nntp/nntpdriver_cached.c + * src/driver/implementation/pop3/pop3driver.c + * src/driver/implementation/pop3/pop3driver_cached.c + * src/driver/implementation/pop3/pop3driver_types.h + * src/driver/implementation/pop3/pop3storage.c + * src/driver/implementation/pop3/pop3storage.h + * src/driver/interface/maildriver.c + * src/driver/interface/maildriver.h + * src/driver/interface/maildriver_types.h + * src/driver/interface/mailstorage_tools.c + * src/driver/interface/mailstorage_tools.h + implemented SASL at higher level API. + + * src/engine/mailprivacy_smime.c + support for Outlook signed messages. + +2005-08-13 - libetpan-0.38cvs2 - hoa + + * src/data-types/mailstream.c + * src/data-types/mailstream_socket.c + * src/data-types/mailstream_ssl.c + * src/driver/implementation/data-message/data_message_driver.c + * src/driver/implementation/db/dbdriver.c + * src/driver/implementation/db/dbdriver_message.c + * src/driver/implementation/db/dbstorage.c + * src/driver/implementation/imap/imapdriver.c + * src/driver/implementation/imap/imapdriver_cached.c + * src/driver/implementation/imap/imapdriver_cached_message.c + * src/driver/implementation/imap/imapdriver_message.c + * src/driver/implementation/imap/imapstorage.c + * src/driver/implementation/maildir/maildirdriver.c + * src/driver/implementation/maildir/maildirdriver_cached.c + * src/driver/implementation/maildir/maildirdriver_cached_message.c + * src/driver/implementation/maildir/maildirdriver_message.c + * src/driver/implementation/maildir/maildirstorage.c + * src/driver/implementation/mbox/mboxdriver.c + * src/driver/implementation/mbox/mboxdriver_cached.c + * src/driver/implementation/mbox/mboxdriver_cached_message.c + * src/driver/implementation/mbox/mboxdriver_message.c + * src/driver/implementation/mbox/mboxstorage.c + * src/driver/implementation/mh/mhdriver.c + * src/driver/implementation/mh/mhdriver_cached.c + * src/driver/implementation/mh/mhdriver_cached_message.c + * src/driver/implementation/mh/mhdriver_message.c + * src/driver/implementation/mh/mhstorage.c + * src/driver/implementation/mime-message/mime_message_driver.c + * src/driver/implementation/nntp/nntpdriver.c + * src/driver/implementation/nntp/nntpdriver_cached.c + * src/driver/implementation/nntp/nntpdriver_cached_message.c + * src/driver/implementation/nntp/nntpdriver_message.c + * src/driver/implementation/nntp/nntpstorage.c + * src/driver/implementation/pop3/pop3driver.c + * src/driver/implementation/pop3/pop3driver_cached.c + * src/driver/implementation/pop3/pop3driver_cached_message.c + * src/driver/implementation/pop3/pop3driver_message.c + * src/driver/implementation/pop3/pop3storage.c + * src/driver/interface/mailstorage_tools.c + * src/engine/mailprivacy_gnupg.c + * src/engine/mailprivacy_smime.c + fixed build on Solaris. + Thanks to Alex S. Moore. + +2005-08-13 - libetpan-0.38cvs1 - hoa + + * src/low-level/mbox/mailmbox.c + switched from LF to CRLF. + Thanks to Alfons Hoogervorst. + +2005-07-20 - libetpan-0.38 - hoa + + * release 0.38 - Deadwing + + * fixed SSL + * IMAP improvements + * SASL + +2005-07-18 - libetpan-0.37cvs6 - hoa + + * src/low-level/imap/mailimap_sender.c + atom is not quoted for now when a dash is to be sent + (workaround a problem in old Courier and old DoveCot IMAP servers) + +2005-07-16 - libetpan-0.37cvs5 - hoa + + * configure.in + * libetpan-config.in + * src/data-types/Makefile + * src/low-level/imap/mailimap.[ch] + * src/low-level/imap/mailimap_sender.[ch] + * src/low-level/imap/mailimap_types.h + * src/low-level/pop3/mailpop3.[ch] + * src/low-level/pop3/mailpop3_types.h + * src/low-level/smtp/mailsmtp.[ch] + * src/low-level/smtp/mailsmtp_types.h + * src/data-types/mailsasl.[ch] ** NEW FILES ** + implemented SASL. + + * src/low-level/imap/mailimap_parser.c + fixed IMAP parser. + +2005-07-15 - libetpan-0.37cvs4 - hoa + + * configure.in + * src/data-types/mailstream_low.c + fixed version number. fixed custom logger. + +2005-07-15 - libetpan-0.37cvs3 - hoa + + * src/data-types/mailstream.h + * src/data-types/mailstream_low.c + changed API for custom logger (added direction of stream). + +2005-07-15 - libetpan-0.37cvs2 - hoa + + * src/data-types/mailstream.h + * src/data-types/mailstream_low.c + added a custom logger for applications. + +2005-07-15 - libetpan-0.37cvs1 - hoa + + * src/data-types/mailstream_ssl.c + fixed SSL write, thanks to Stephan Holl, Colin Leroy + +2005-07-03 - libetpan-0.37 - hoa + + * release 0.37 - Deadwing + + * windows port + * fixed IMAP implementation (for sylpheed) + +2005-06-28 - libetpan-0.36cvs18 - hoa + + * src/low-level/imap/mailimap_sender.c + fixed storage of flags. + +2005-06-19 - libetpan-0.36cvs17 - hoa + + * src/driver/implementation/mbox/mboxdriver_cached.c + fixed double fclose(). Thanks to Nyoxi. + +2005-06-13 - libetpan-0.36cvs16 - hoa + + * src/engine/mailengine.c + fixed thread safety for reference count. + + * src/low-level/mh/mailmh.c + fixed MH (addition of messages). + +2005-06-01 - libetpan-0.36cvs15 - hoa + + * libetpan-config.h.in + * src/data-types/maillock.c + * src/driver/implementation/maildir/maildirdriver_cached_message.c + * src/driver/implementation/maildir/maildirdriver_message.c + * src/driver/implementation/mh/mhdriver_tools.c + * src/driver/implementation/nntp/nntpdriver_cached.c + * src/driver/interface/maildriver_tools.c + * src/driver/tools/generic_cache.c + * src/low-level/imap/mailimap_types.h + * src/low-level/imf/mailimf_types.h + * src/low-level/imf/mailimf_types_helper.c + * src/low-level/maildir/maildir_types.h + * src/low-level/mh/mailmh.h + * src/low-level/mime/mailmime_types_helper.c + * src/low-level/mime/mailmime_write_generic.c + * src/low-level/nntp/newsnntp_types.h + * src/low-level/pop3/mailpop3_types.h + * src/low-level/smtp/mailsmtp_socket.h + * src/low-level/smtp/mailsmtp_types.h + * src/windows/win_etpan.h + * src/windows/wsocket.cpp + fixed linux build. + +2005-06-01 - libetpan-0.36cvs14 - hoa + + * src/data-types/mail_cache_db.c + * src/driver/implementation/db/dbdriver.c + * src/driver/implementation/imap/imapdriver_cached.c + * src/driver/implementation/imap/imapdriver_tools.c + * src/driver/implementation/maildir/maildirdriver_cached.c + * src/driver/implementation/mbox/mboxdriver_cached.c + * src/driver/implementation/mh/mhdriver_cached.c + * src/driver/implementation/nntp/nntpdriver.c + * src/driver/tools/generic_cache.c + * src/driver/tools/imfcache.c + * src/engine/mailprivacy.c + * src/engine/mailprivacy_smime.c + * src/low-level/imap/mailimap_parser.c + * src/low-level/imap/mailimap_sender.c + * src/low-level/imf/mailimf.c + * src/low-level/mbox/mailmbox.c + * src/low-level/mime/mailmime.c + * src/low-level/mime/mailmime_decode.c + * src/low-level/mime/mailmime_disposition.c + * src/low-level/nntp/newsnntp.c + * src/low-level/pop3/mailpop3.c + * src/low-level/smtp/mailsmtp.c + fixed gcc 4.0 warnings. + +2005-06-01 - libetpan-0.36cvs13 - hoa + + * src/data-types/maillock.c + * src/data-types/mailstream_socket.c + fixed some warnings. + +2005-06-01 - libetpan-0.36cvs12 - smarinier + + * most files + Windows port + +2005-05-27 - libetpan-0.36cvs11 - hoa + + * src/data-types/chash.c + don't use tables of size 0. + + * src/data-types/mailsem.c + includes missing header. + + * src/engine/mailprivacy_smime.c + insert part even if decoding failed. + +2005-05-22 - libetpan-0.36cvs10 - g_roualland + + * configure.in + * Makefile.in + change the way libetpan-config.h is generated to cope with + cross compilers and external build directories. + +2005-05-19 - libetpan-0.36cvs9 - hoa + + * src/driver/interface/mailfolder.c + reconnect on POP3 fetch of message list. + + * src/low-level/pop3/mailpop3.c + fixed crash on mailpop3_quit() in case + of bad state. + +2005-04-25 - libetpan-0.36cvs8 - hoa + + * src/data-types/mail_cache_db.c + fixed test of error codes. + +2005-04-18 - libetpan-0.36cvs7 - hoa + + * src/data-types/carray.c + don't allow zero-sized array. + That will avoid infinite loops. + +2005-04-12 - libetpan-0.36cvs6 - hoa + + * src/data-types/mailsem.c + use unique implementation of semaphore. + +2005-04-08 - libetpan-0.36cvs5 - hoa + + * src/data-types/mail_cache_db.c + fixed test of error codes. + +2005-04-07 - libetpan-0.36cvs5 - hoa + + * autogen.sh + support for Mac OS X + + * src/data-types/charconv.c + fixed error code. + + * src/data-types/mail_cache_db.c + * src/data-types/mail_cache_db.h + added function to retrieve the list of keys. + + * src/data-types/mailsem.c + fixed semaphore. + + * src/driver/tools/mailthread.c + made mailthread thread safe. + +2005-03-12 - libetpan-0.36cvs4 - hoa + + * configure.in + * src/Makefile.in + * src/data-types/mailstream_ssl.c + support for GNUTLS. + Thanks from Rajko Albrecht. + + * src/data-types/mailsem.c + disable semaphore when reentrant support is disabled. + Thanks from Rajko Albrecht. + + * src/driver/implementation/imap/imapdriver_cached.c + fixed false error in cached IMAP driver. + +2005-03-04 - libetpan-0.36cvs3 - hoa + + * src/data-types/mail_cache_db.c + reorder unlock() and close() + + * src/data-types/mailsem.c + implements properly the semaphore. + +2005-02-28 - libetpan-0.36cvs2 - hoa + + * Rules.in + fixed build when the exported header list is empty. + Thanks to Alfons Hoogervorst. + + * doc/README.sgml + removed version numbers. + +2005-02-28 - libetpan-0.36cvs1 - g_roualland + + * src/data-types/mail_cache_db.c + fix DB cursor call when running on db2 < 2.6 + Thanks to Alfons Hoogervorst. + +2005-02-22 - libetpan-0.36 - hoa + + * release 0.36 - Silver Drop + + * memory leak + * fixed maildir support + +2005-02-17 - libetpan-0.35cvs4 - hoa + + * src/engine/mailprivacy.c + does not check for owner of the folder: + this is the responsibility of the application. + +2005-01-31 - libetpan-0.35cvs3 - hoa + + * src/data-types/mmapstring.c + * src/engine/mailengine.c + reverted to initial in code in non-debug mode. + fixed thread safety. + +2005-01-29 - libetpan-0.35cvs2 - hoa + + * src/driver/implementation/imap/imapdriver_cached.c + * src/low-level/mime/mailmime_types.c + fixed some memory leaks. + +2005-01-28 - libetpan-0.35cvs1 - hoa + + * src/data-types/mailsem.c + support for Cygwin. + + * src/driver/implementation/db/dbdriver.c + removed a log. + + * src/driver/implementation/nntp/nntpdriver_cached.c + * src/engine/mailengine.c + fixed some memory leaks. + + * src/engine/mailprivacy_tools.c + internal version of basename() can be used. + + * src/low-level/maildir/maildir.c + fixed update of Maildir mailbox. + + * src/low-level/pop3/mailpop3.[ch] + fixed data types to non-fixed size integers. + +2004-12-28 - libetpan-0.35 - hoa + + * release 0.35 - Dimebag Darrell + + * minor bugfixes. + +2004-12-27 - libetpan-0.34cvs8 - hoa + + * src/engine/mailprivacy_gnupg.c + * src/engine/mailprivacy_smime.c + fixed syntax error. + + * src/low-level/maildir/maildir.c + avoid stat() on maildir files. + + * src/main/libetpan.h + enabled hotmailstorage. + +2004-12-13 - libetpan-0.34cvs7 - hoa + + * src/driver/implementation/mime-message/mime_message_driver.[ch] + MIME message driver will no more need temporary files. + +2004-12-13 - libetpan-0.34cvs6 - hoa + + * src/low-level/mime/mailmime_content.c + fixed MIME parser. MIME parts does not include + the boundary CR LF. + +2004-12-12 - libetpan-0.34cvs5 - hoa + + * src/data-types/mail_cache_db.c + * src/driver/implementation/db/dbdriver.c + fixed data types and uninitialized variable. + + * src/driver/implementation/maildir/maildirdriver_tools.c + * src/driver/implementation/mh/mhdriver_tools.c + * src/driver/interface/maildriver_errors.h + * src/low-level/imap/mailimap_parser.c + * src/low-level/maildir/maildir.c + * src/low-level/maildir/maildir_types.h + * src/low-level/mh/mailmh.c + now use rename() when link() is not available. + Thanks to Lutz Rogowski. + + * src/low-level/mime/mailmime_decode.c + fixed a memory leak. Thanks to Lutz Rogowski. + +2004-11-14 - libetpan-0.34cvs4 - hoa + + * src/low-level/mime/mailmime_content.c + fixed MIME parser. + Problem appeared when there when a boundary identifier + was prefix of an other boundary identifier (1065539). + +2004-11-14 - libetpan-0.34cvs3 - hoa + + * src/low-level/maildir/maildir.c + maildir_update() now creates an empty file named maildirfolder. + +2004-11-14 - libetpan-0.34cvs2 - hoa + + * src/data-types/maillock.c + fixed locks when using liblockfile. + +2004-11-13 - libetpan-0.34cvs1 - hoa + + * src/data-types/maillock.c + fixed locks when using liblockfile. + + * src/data-types/mmapstring.c + additional checks. + + * src/driver/interface/maildriver_errors.h + clean up of code. + + * src/low-level/imf/Makefile + * src/low-level/imf/mailimf.h + * src/low-level/imf/mailimf_write_file.[ch] ** NEW FILES ** + * src/low-level/imf/mailimf_write_mem.[ch] ** NEW FILES ** + * src/low-level/mime/Makefile + * src/low-level/mime/mailmime.h + * src/low-level/mime/mailmime_write_file.[ch] ** NEW FILES ** + * src/low-level/mime/mailmime_write_mem.[ch] ** NEW FILES ** + messages can be rendered into a MMAPString. + +2004-11-04 - libetpan-0.34 - hoa + + * release 0.34 - edge + + * general + - support for debian systems mbox + - ability to disable thread-safe support + +2004-11-04 - libetpan-0.33cvs7 - hoa + + * src/data-types/mailstream.c + * src/data-types/mailstream_helper.[ch] + * src/data-types/mailstream_low.c + debug logs are just before low-level. + helper functions to send multi-lines data. + + * src/driver/implementation/imap/imapdriver.c + * src/driver/implementation/imap/imapdriver_cached.c + limit requests to imap server (compatibility with iPlanet). + + * src/low-level/imap/mailimap.c + * src/low-level/imap/mailimap_sender.c + fixed send of literal, add proper CR LF + (compatibility with Cyrus). + + * src/low-level/mh/mailmh.h + removed reference to deprecated cinthash + + * src/low-level/nntp/newsnntp.h + removed inexistant function in header. + +2004-10-17 - libetpan-0.33cvs6 - g_roualland + + * configure.in + Add a "--disable-threads" option to compile without pthread. + In that case the library is named as "libetpan-no-mt". + Added a LIBETPAN_REENTRANT define which is true if multithreading + is available. + Added pthread avaibility detection. + + * libetpan-config.in + * src/Makefile.in + update to include thread options and the correct name for the + library. fix make clean to remove libs + + * src/main/libetpan-version.h.in + define LIBETPAN_REENTRANT if the library was compiled as + reentrant. + + * src/data-types/mailstream_ssl.c + * src/data-types/mmapstring.c + * src/engine/mailengine.c + do not include pthread calls if not reentrant. + +2004-10-17 - libetpan-0.33cvs5 - hoa + + * Makefile.in + * Rules.in + fixed precopy of headers. + + * src/low-level/mbox/mailmbox.c + fixed write of mailbox files on debian systems. + + * src/low-level/mime/mailmime_write.c + fixed a bug. Thanks to Melvin. + +2004-09-29 - libetpan-0.33cvs4 - hoa + + * configure.in + * src/data-types/maillock.c + * src/low-level/mbox/mailmbox.c + support for mailboxes on debian systems. + +2004-09-03 - libetpan-0.33cvs3 - hoa + + * src/engine/mailengine.c + can remove storage or folder twice. + +2004-09-02 - libetpan-0.33cvs2 - hoa + + * src/driver/interface/maildriver_errors.h + * src/driver/tools/mailthread.[ch] + * src/driver/tools/mailthread_types.h + can build a tree of messages without message threading + + * src/data-types/mailsem.[ch] + added semaphore + + +2004-08-28 - libetpan-0.33cvs1 - hoa + + * src/driver/implementation/mh/mhdriver_tools.c + fixed the workaround MH mailboxes with messages + containing 'From ' header. + + +2004-08-24 - libetpan-0.33 - hoa + + * release 0.33 - entropia + + * general + - bugfixes in IMAP module and mailstream + - fixed low-level data structures + - better support for ARM and PPC architecture + - support for cross-compilation + - fixed Berkeley DB support + - changed folder structure of libetpan package + - can now add a message to a mailbox with flags + - support for hotmail mailboxes (with help of hotwayd) + - added Berkeley DB mail storage as experimental + - added support for PGP and S/MIME + - better folder API + + +2004-08-22 - libetpan-0.32cvs18 - hoa + + * Makefile.in + * Rules.in + * src/main/libetpan.h + Fixed header inclusion. + Fixed installation of headers. + +2004-08-22 - libetpan-0.32cvs17 - hoa + + * Makefile.in + * autogen.sh + * configure.in + * src/Makefile.in + * src/main/libetpan.h + Better detection of iconv. + Some fixes in build process. + Documentation is generated at prepackaging. + Engine added to build process. + + * doc/API.sgml + * doc/Makefile + * doc/README.sgml + Updated documentation + + * src/data-types/charconv.c + Better detection of iconv. + + * src/data-types/mail_cache_db.c + Fixed db wrapper. + + * src/driver/implementation/mbox/mboxdriver_cached.c + * src/driver/implementation/mbox/mboxdriver_cached_message.c + * src/driver/implementation/mbox/mboxdriver_message.c + * src/driver/implementation/mbox/mboxdriver_tools.c + * src/driver/implementation/mh/mhdriver_cached.c + * src/driver/implementation/mh/mhdriver_cached_message.c + * src/driver/implementation/mh/mhdriver_message.c + * src/driver/implementation/mh/mhdriver_tools.c + Fixed format of UID, in several drivers. + + * src/driver/interface/mailfolder.c + * src/driver/interface/mailfolder.h + * src/driver/interface/mailstorage.c + * src/driver/interface/mailstorage.h + we can now append messages with their flags. + + * src/engine/Makefile + * src/engine/mailengine.c + * src/engine/mailengine.h + * src/engine/mailprivacy.h + * src/engine/mailprivacy_gnupg.c + * src/engine/mailprivacy_gnupg.h + * src/engine/mailprivacy_smime.c + * src/engine/mailprivacy_smime.h + * src/engine/mailprivacy_tools.c + * src/engine/mailprivacy_tools.h + * src/engine/mailprivacy_types.h + * src/low-level/imap/mailimap_keywords.c + * src/low-level/mbox/mailmbox.c + * src/low-level/mime/mailmime_write.c + remove hash global to storage to find folder of messages + +2004-07-28 - libetpan-0.32cvs16 - g_roualland + + * acconfig.h * REMOVED FILE * + * configure.in + Convert old, deprecated autoconf defines to 2.5 like. + + * Makefile.in + Do not look for acconfig.h, remove autoconf cache on clean. + + * src/Makefile.in + Make sure "make clean" works even when the library was not built. + + * Makefile.in + * Rules.in + * src/Makefile.in + Support for DESTDIR to install in another root. + Patch from Rajko Albrecht <ral@alwins-world.de> + + * src/driver/implementation/imap/imapdriver_cached_message.c + Fix a GCC 3.4 compiling issue with labels. + Patch from Rajko Albrecht <ral@alwins-world.de> + +2004-05-23 - libetpan-0.32cvs15 - hoa + + * Makefile.in + * Rules.in + fixed building and installing. + + * configure.in + improved support for Berkeley DB + (thanks to Nikita V. Youshchenko). + + * doc/README.sgml + updated documentation. + + * src/data-types/mail_cache_db.[ch] + added function to get size of a given item. + + * src/data-types/mailstream_helper.c + fixed a crash when sending of data. + + * src/driver/implementation/Makefile + * src/driver/implementation/imap/imapstorage.c + * src/driver/implementation/mbox/mboxdriver_cached.c + * src/driver/implementation/mbox/mboxstorage.c + * src/driver/implementation/mh/mhstorage.c + * src/driver/implementation/nntp/nntpstorage.c + code cleanup. + + * src/driver/implementation/pop3/pop3driver_cached.c + * src/driver/implementation/pop3/pop3driver_message.c + * src/driver/implementation/pop3/pop3storage.c + implemented get_message_by_uid() + (Thanks to Toni Willberg). + + * src/driver/implementation/maildir/maildirdriver_cached_message.c + * src/driver/implementation/maildir/maildirdriver_message.c + * src/driver/implementation/maildir/maildirstorage.[ch] + implemented get_flags(). + + * src/main/libetpan.h + * src/driver/implementation/db/Makefile ** NEW FILE ** + * src/driver/implementation/db/dbdriver.[ch] ** NEW FILES ** + * src/driver/implementation/db/dbdriver_message.[ch] ** NEW FILES ** + * src/driver/implementation/db/dbdriver_types.h ** NEW FILE ** + * src/driver/implementation/db/dbstorage.[ch] ** NEW FILES ** + added mail DB driver (using a Berkeley DB storage). + + * hotmail/Makefile ** NEW FILE ** + * hotmail/hotmailstorage.[ch] ** NEW FILES ** + added support for hotmail (using hotwayd and POP3 driver) + + * tests/Makefile + * tests/readmsg-uid.c ** NEW FILE ** + added example for get_message_by_uid() + +2004-05-04 - libetpan-0.32cvs14 - hoa + + * src/driver/implementation/imap/imapdriver.c + * src/driver/implementation/imap/imapdriver_cached.c + * src/driver/implementation/imap/imapdriver_tools.[ch] + * src/driver/implementation/maildir/maildirdriver.c + * src/driver/implementation/maildir/maildirdriver_cached.c + * src/driver/implementation/mbox/mboxdriver.c + * src/driver/implementation/mbox/mboxdriver_cached.c + * src/driver/implementation/mh/mhdriver.c + * src/driver/implementation/mh/mhdriver_cached.c + * src/driver/implementation/nntp/nntpdriver.c + * src/driver/implementation/nntp/nntpdriver_cached.c + * src/driver/implementation/pop3/pop3driver.c + * src/driver/implementation/pop3/pop3driver_cached.c + * src/driver/interface/maildriver.[ch] + * src/driver/interface/maildriver_types.h + mailsession_append_message_flags() adds a message + in a mailbox with its flags. It is implemented in + IMAP, mbox, maildir and MH drivers. + + * src/low-level/maildir/maildir.[ch] + * src/low-level/mbox/mailmbox.[ch] + * src/low-level/mbox/mailmbox_types.[ch] + * src/low-level/mh/mailmh.[ch] + get identifier of the message when we add a message + in a mailbox. + +2004-05-02 - libetpan-0.32cvs13 - hoa + + * Makefile.in + * Rules.in + * configure.in + * src/Makefile.in * NEW FILES * + * src/data-types/Makefile + * src/data-types/mmapstring.c + * src/driver/Makefile + * src/driver/implementation/Makefile * NEW FILES * + * src/driver/implementation/data-message/Makefile * NEW FILES * + * src/driver/implementation/imap/Makefile * NEW FILES * + * src/driver/implementation/maildir/Makefile * NEW FILES * + * src/driver/implementation/mbox/Makefile * NEW FILES * + * src/driver/implementation/mbox/mboxdriver_message.c + * src/driver/implementation/mh/Makefile * NEW FILES * + * src/driver/implementation/mime-message/Makefile * NEW FILES * + * src/driver/implementation/nntp/Makefile * NEW FILES * + * src/driver/implementation/pop3/Makefile * NEW FILES * + * src/driver/interface/Makefile * NEW FILES * + * src/driver/tools/Makefile * NEW FILES * + * src/engine/Makefile * NEW FILES * + * src/engine/mailengine.[ch] * NEW FILES * + * src/engine/mailprivacy.[ch] * NEW FILES * + * src/engine/mailprivacy_gnupg.[ch] * NEW FILES * + * src/engine/mailprivacy_smime.[ch] * NEW FILES * + * src/engine/mailprivacy_tools.[ch] * NEW FILES * + * src/engine/mailprivacy_types.h * NEW FILES * + * src/low-level/Makefile * NEW FILES * + * src/low-level/imap/Makefile + * src/low-level/imf/Makefile + * src/low-level/imf/mailimf.c + * src/low-level/maildir/Makefile + * src/low-level/mbox/Makefile + * src/low-level/mh/Makefile + * src/low-level/mime/Makefile + * src/low-level/nntp/Makefile + * src/low-level/pop3/Makefile + * src/low-level/smtp/Makefile + * src/main/Makefile * NEW FILES * + changed folders structure + +2004-03-23 - libetpan-0.32cvs12 - hoa + + * tools/mmapstring.c + fixed a bug when initializing a string of size 0. + That lead to a bug when fetching a part of size 0. + +2004-03-13 - libetpan-0.32cvs11 - hoa + + * tools/mailstream_socket.c + revert of previous commit (this is not POSIX). + +2004-03-13 - libetpan-0.32cvs10 - hoa + + * tools/mailstream_socket.c + socket failures send no more signals. + +2004-03-13 - libetpan-0.32cvs9 - hoa + + * mime/mailmime_decode.c + better checks in mailmime_encoded_phrase_decode() + Thanks to Frederic Devernay + +2004-03-13 - libetpan-0.32cvs8 - g_roualland + + * smtp/mailsmtp_helper.c + Fix esmtp status corruption in mailesmtp_init. + Patch from Rajko Albrecht <ral@alwins-world.de>) + + * smtp/mailsmtp.c + Make sure to reset esmtp status on HELO. + +2004-03-03 - libetpan-0.32cvs7 - hoa + + * configure.in + * imap/mailimap.c + * tools/charconv.c + possibility to disable iconv. Fixed some leaks. + Thanks to Frederic Devernay. + + * tools/mailstream_socket.c + * mime/mailmime_decode.c + some support for broken architecture such as ARM. + Thanks to Rajko Albrecht. + +2004-02-28 - libetpan-0.32cvs6 - hoa + + * tools/mail_cache_db.c + read/write cache database when support for Berkeley DB 1.x + is enabled (this fix a bug where the database was readonly). + +2004-01-23 - libetpan-0.32cvs5 - melvin + + * libetpan-config.h.in + Better support for ARM: include both limits.h and sys/params.h + if both are available. ARM requires this. + Patch from Rajko Albrecht <ral@alwins-world.de>. + +2004-01-20 - libetpan-0.32cvs4 - melvin + + * imap/mailimap_types.h + * imap/mailimap_types.c + * imap/mailimap_print.c + Fixed concurrent usage of two members of the same union + that resulted in double memory free after parsing some IMAP + responses (as in ...[APPENDUID VID UID]) + * generic/mailmessage_types.c + * generic/mailstorage_tools.c + * tools/maillock.c + Added <string.h> header + * tools/connect.c + * tools/mail_cache_db.c + Added <unistd.h> header + +2004-01-12 - libetpan-0.32cvs3 - hoa + + * configure.in + detection of Berkeley DB can be disabled. + + * doc/API.sgml + * doc/Makefile + * doc/README.sgml + updated documentation + + * generic/Makefile + * generic/mailstorage_tools.c + * generic/mailfolder.[ch] * NEW FILES * + destroy the unused file descriptors. + folder API. + + * mime/mailmime_content.c + fixed a problem in MIME parser on architectures where + char is unsigned. + + * tools/connect.c + destroy the unused file descriptors. + +2004-01-07 - libetpan-0.32cvs2 - g_roualland + + * smtp/mailsmtp.c + * smtp/mailsmtp.h + * smtp/mailsmtp_types.h + added full parsing of ehlo answer to detect esmtp extensions + added mailsmtp_starttls() command. + + * smtp/mailsmtp_socket.c + * smtp/mailsmtp_socket.h + added mailsmtp_socket_starttls to switch a connected + ESMTP session under a TLS layer. + + * tests/smtpsend.c + updated to make use of starttls and esmtp extensions. + +2003-12-23 - libetpan-0.32cvs1 - hoa + + * imap/mailimap_types.c + fixed a crash related to capabilities. + +2003-12-16 - libetpan-0.32 - hoa + + * release 0.32 - Black Utopia + + * general + - added documentation for IMF / tools + - bugfixes in IMAP module due to structures change. + - Application that use libEtPan! now have to use + '#include <libetpan/libetpan.h>' + + * generic + - get_message() is implemented in Maildir cached driver. + +2003-12-15 - libetpan-0.31cvs7 - hoa + + * Makefile.in + * Rules.in + fixed dependencies in Makefiles. + +2003-12-15 - libetpan-0.31cvs6 - hoa + + * Makefile.in + "make clean" does no more delete install include directory. + +2003-12-15 - libetpan-0.31cvs5 - hoa + + * Makefile.in + some cleanup. + + * libetpan-config.h.in * NEW FILE * + added missing file. + + * generic/maildirdriver.c + added get_message_by_uid() + + * generic/maildirdriver_cached.c + added get_message_by_uid() and get_message() + index for the message is persistant in cached driver. + + * libetpan-config.in + don't add -I/usr/include if /usr is the prefix. + +2003-12-15 - libetpan-0.31cvs4 - hoa + + * Makefile.in + some cleanup. + + * libetpan-config.h.in * NEW FILE * + added missing file. + + * generic/maildirdriver.c + added get_message_by_uid() + + * generic/maildirdriver_cached.c + added get_message_by_uid() and get_message() + index for the message is persistant in cached driver. + + * libetpan-config.in + don't add -I/usr/include if /usr is the prefix. + +2003-12-15 - libetpan-0.31cvs4 - hoa + + * Makefile.in + * Rules.in + * configure.in + * libetpan-config.in + * generic/Makefile + * generic/data_message_driver.[ch] + * generic/generic_cache.c + * generic/generic_cache_types.h + * generic/imapdriver.[ch] + * generic/imapdriver_cached.[ch] + * generic/imapdriver_cached_message.h + * generic/imapdriver_message.h + * generic/imapdriver_tools.c + * generic/imapdriver_types.h + * generic/imapstorage.[ch] + * generic/libetpan.h + * generic/maildirdriver.h + * generic/maildirdriver_cached.[ch] + * generic/maildirdriver_cached_message.h + * generic/maildirdriver_message.h + * generic/maildirdriver_types.h + * generic/maildirstorage.[ch] + * generic/maildriver.h + * generic/maildriver_tools.c + * generic/maildriver_types.h + * generic/maildriver_types_helper.[ch] + * generic/mailmessage.[ch] + * generic/mailmessage_types.[ch] + * generic/mailstorage.h + * generic/mailstorage_tools.[ch] + * generic/mailthread.[ch] + * generic/mailthread_types.[ch] + * generic/mboxdriver.[ch] + * generic/mboxdriver_cached.[ch] + * generic/mboxdriver_cached_message.h + * generic/mboxdriver_message.h + * generic/mboxdriver_types.h + * generic/mboxstorage.[ch] + * generic/mhdriver.h + * generic/mhdriver_cached.[ch] + * generic/mhdriver_cached_message.h + * generic/mhdriver_message.h + * generic/mhdriver_types.h + * generic/mhstorage.[ch] + * generic/mime_message_driver.[ch] + * generic/nntpdriver.[ch] + * generic/nntpdriver_cached.[ch] + * generic/nntpdriver_cached_message.h + * generic/nntpdriver_message.h + * generic/nntpdriver_tools.c + * generic/nntpdriver_types.h + * generic/nntpstorage.[ch] + * generic/pop3driver.h + * generic/pop3driver_cached.[ch] + * generic/pop3driver_cached_message.h + * generic/pop3driver_message.h + * generic/pop3driver_types.h + * generic/pop3storage.[ch] + * imap/mailimap.[ch] + * imap/mailimap_helper.h + * imap/mailimap_parser.c + * imap/mailimap_sender.c + * imap/mailimap_socket.h + * imap/mailimap_ssl.h + * imap/mailimap_types.[ch] + * imap/mailimap_types_helper.[ch] + * imf/mailimf.h + * imf/mailimf_types.h + * imf/mailimf_types_helper.h + * imf/mailimf_write.h + * maildir/maildir.[ch] + * maildir/maildir_types.h + * mbox/mailmbox.c + * mbox/mailmbox.h + * mbox/mailmbox_types.h + * mh/mailmh.[ch] + * mime/mailmime.h + * mime/mailmime_content.h + * mime/mailmime_decode.h + * mime/mailmime_disposition.h + * mime/mailmime_types.h + * mime/mailmime_types_helper.h + * mime/mailmime_write.h + * nntp/newsnntp.h + * nntp/newsnntp_socket.h + * nntp/newsnntp_ssl.h + * nntp/newsnntp_types.h + * pop3/mailpop3.h + * pop3/mailpop3_socket.h + * pop3/mailpop3_ssl.h + * pop3/mailpop3_types.h + * smtp/mailsmtp.[ch] + * smtp/mailsmtp_helper.c + * smtp/mailsmtp_socket.h + * smtp/mailsmtp_ssl.h + * smtp/mailsmtp_types.h + * tests/compose-msg.c + * tests/fetch-attachment.c + * tests/frm-common.[ch] + * tests/frm-simple.c + * tests/frm-tree.c + * tests/frm.c + * tests/option-parser.[ch] + * tests/readmsg-common.[ch] + * tests/readmsg-simple.c + * tests/readmsg.c + * tests/smtpsend.c + * tools/Makefile + * tools/carray.h + * tools/mail.h + * tools/mail_cache_db.c + * tools/maillock.c + * tools/mailstream.h + * tools/mailstream_helper.[ch] + * tools/mailstream_low.h + * tools/mailstream_socket.h + * tools/mailstream_ssl.h + * tools/mailstream_types.h + * tools/mmapstring.c + fixed some dependencies. + Application that use libEtPan! now have to use + '#include <libetpan/libetpan.h>' + #include <libetpan.h> still exists for backward compatibility. + API version (with libtool) has been introduced. + +2003-12-14 - libetpan-0.31cvs3 - hoa + + * Makefile.in + fixed dependencies. + + * generic/maildriver_tools.c + * generic/mailstorage_tools.c + added missing includes. + + * imf/mailimf_types.h + fixed documentation. + +2003-12-11 - libetpan-0.31cvs2 - hoa + + * tools/carray.h + fixed prototype of non-macro version. + +2003-12-11 - libetpan-0.31cvs1 - hoa + + * configure.in + * imap/mailimap_helper.c + * imap/mailimap_parser.c + * imap/mailimap_print.c + * imap/mailimap_sender.c + * imap/mailimap_types.[ch] + now sends empty astring as "". + fixed a problem when fetching RFC822[.XXX] parts. + fixed a problem with mailbox flags. + +2003-12-10 - libetpan-0.31 - hoa + + * release 0.31 - Steve Morse release + + * general + - all fields name of structures are changed. + - bugfixes. + - union {} are added everywhere it is possible to save memory. + - support for Berkeley DB 1. + - improved compatibility with FreeBSD and Mac OS X. + + * drivers + - cache drivers are disable if Berkeley DB is not found. + - disable search call. + - support of buggy Courier-IMAP server. + - semantic of mailsession_get_envelopes_list() changed : it + does no more remove messages from the list. + - mailsession_get_message_by_uid() is added and implemented + in some drivers. + +2003-12-10 - libetpan-0.30-cvs22 - hoa + + * configure.in + * tools/mail_cache_db.c + if Berkeley DB is not found, cached drivers are disabled. + + * generic/mailmessage_tools.c + * generic/mhdriver_tools.c + * generic/mime_message_driver.c + fetch_header(), fetch_section_header(), fetch_section_mime() + returns the ending single CRLF line for all drivers. + + * tests/compose-msg.c + * tests/fetch-attachment.c + * tests/frm-common.c + * tests/frm-simple.c + * tests/frm-tree.c + * tests/frm.c + * tests/option-parser.c + * tests/readmsg.c + fixed examples. Add static keyword where needed, forbid use + of 'msg->msg_single_fields'. + +2003-12-08 - libetpan-0.30-cvs21 - hoa + + * tests/fetch-attachment.c + * tests/frm-simple.c + * tests/frm-tree.c + * tests/frm.c + * tests/option-parser.[ch] + * tests/readmsg-simple.c + * tests/readmsg.c + * tests/frm-common.[ch] * NEW FILES * + conform to new API. + added missing files frm-common.[ch] + +2003-12-08 - libetpan-0.30-cvs20 - hoa + + * generic/generic_cache.[ch] + * generic/generic_cache_types.h + * generic/maildriver_types.[ch] + * generic/maildriver.[ch] + * generic/maildriver_tools.[ch] + * generic/maildriver_types_helper.c + * generic/mailmessage.[ch] + * generic/mailmessage_tools.c + * generic/mailmessage_types.c + * generic/mailstorage.[ch] + * generic/mailstorage_tools.[ch] + * generic/mailstorage_types.h + * generic/mailthread.[ch] + * generic/mailthread_types.c + prefix field names. + reflect the changes in the naming. + changed prototype of storage uninitializer. + changed prototype of session initializer. + removed mail_search_key related things. + + * generic/data_message_driver.c + * generic/imfcache.c + * generic/mime_message_driver.c + reflect the changes in the naming. + + * generic/imapdriver.[ch] + * generic/imapdriver_cached.[ch] + * generic/imapdriver_cached_message.c + * generic/imapdriver_message.c + * generic/imapdriver_tools.[ch] + * generic/imapdriver_types.h + * generic/imapstorage.[ch] + reflect the changes in the naming. + additionnally, imapdriver becomes imap_session_driver + and imapdriver_cached becomes imap_cached_session_driver. + + * generic/libetpan.h + drivers are now included in this header. + + * generic/maildirdriver.[ch] + * generic/maildirdriver_cached.[ch] + * generic/maildirdriver_cached_message.c + * generic/maildirdriver_message.c + * generic/maildirdriver_tools.[ch] + * generic/maildirdriver_types.h + * generic/maildirstorage.[ch] + reflect the changes in the naming. + additionnally, maildirdriver becomes maildir_session_driver + and maildirdriver_cached becomes + maildir_cached_session_driver. + + * generic/mboxdriver.[ch] + * generic/mboxdriver_cached.[ch] + * generic/mboxdriver_cached_message.c + * generic/mboxdriver_message.c + * generic/mboxdriver_tools.[ch] + * generic/mboxdriver_types.h + * generic/mboxstorage.[ch] + reflect the changes in the naming. + additionnally, mboxdriver becomes mbox_session_driver + and mboxdriver_cached becomes mbox_cached_session_driver. + + * generic/mhdriver.[ch] + * generic/mhdriver_cached.[ch] + * generic/mhdriver_cached_message.c + * generic/mhdriver_message.c + * generic/mhdriver_tools.[ch] + * generic/mhdriver_types.h + * generic/mhstorage.[ch] + reflect the changes in the naming. + additionnally, mboxdriver becomes mh_session_driver + and mhdriver_cached becomes mh_cached_session_driver. + + * generic/nntpdriver.[ch] + * generic/nntpdriver_cached.[ch] + * generic/nntpdriver_cached_message.c + * generic/nntpdriver_message.c + * generic/nntpdriver_tools.[ch] + * generic/nntpdriver_types.h + * generic/nntpstorage.[ch] + reflect the changes in the naming. + additionnally, nntpdriver becomes nntp_session_driver + and nntpdriver_cached becomes nntp_cached_session_driver. + + * generic/pop3driver.[ch] + * generic/pop3driver_cached.[ch] + * generic/pop3driver_cached_message.c + * generic/pop3driver_message.c + * generic/pop3driver_tools.[ch] + * generic/pop3driver_types.h + * generic/pop3storage.[ch] + reflect the changes in the naming. + additionnally, pop3driver becomes pop3_session_driver + and pop3driver_cached becomes pop3_cached_session_driver. + + * imap/mailimap.c + * imap/mailimap_print.c + * imap/mailimap_sender.c + * imf/mailimf_types_helper.c + * imf/mailimf_write.c + * mime/mailmime.c + * mime/mailmime_content.c + * mime/mailmime_types.c + * mime/mailmime_types_helper.c + * nntp/newsnntp.c + * smtp/mailsmtp_helper.c + proper use of clist_content(), clist_next(), carray_count() + and carray_data(). + +2003-12-05 - libetpan-0.30-cvs19 - hoa + + * generic/imapdriver.c + don't fail if SEARCH command is not supported by the server. + + * configure.in + improved autodetection of Berkeley DB version. + Thanks to Keith Edmunds. + +2003-12-04 - libetpan-0.30-cvs18 - hoa + + * generic/generic_cache.c + * generic/imapdriver.c + * generic/imapdriver_cached.c + * generic/imapdriver_tools.c + * generic/maildirdriver.c + * generic/maildirdriver_cached.c + * generic/maildirdriver_tools.c + * generic/maildriver_tools.c + * generic/maildriver_types.c + * generic/mailstorage.c + * generic/mailstorage_types.h + * generic/mailthread.c + * generic/mailthread_types.c + * generic/mboxdriver.c + * generic/mboxdriver_cached.c + * generic/mboxdriver_message.c + * generic/mboxdriver_tools.c + * generic/mhdriver.c + * generic/mhdriver_cached.c + * generic/mhdriver_cached_message.c + * generic/mhdriver_message.c + * generic/mhdriver_tools.c + * generic/nntpdriver.c + * generic/nntpdriver_cached.c + * generic/nntpdriver_tools.c + * generic/pop3driver.c + * generic/pop3driver_cached.c + * generic/pop3driver_tools.c + * maildir/maildir.c + * mbox/mailmbox.c + * mbox/mailmbox_parse.c + * mbox/mailmbox_types.[ch] + * mh/mailmh.[ch] + * pop3/mailpop3.c + * pop3/mailpop3_types.h + * tests/frm-simple.c + * tests/frm-tree.c + * tests/frm.c + * tests/readmsg-common.c + * tools/carray.[ch] + * tools/chash.[ch] + * tools/mmapstring.c + changed carray and chash structure to easy use of them. + reflect these changes on the whole code. + +2003-12-03 - libetpan-0.30-cvs17 - hoa + + * mh/mailmh.[ch] + don't update folder implicitely. + + * generic/mhdriver.c + * generic/mhdriver_cached.c + * generic/mhdriver_cached_message.c + * generic/mhdriver_message.c + * generic/mhdriver_tools.c + fixed MH driver status and expunge. + + * generic/imapstorage.h + removed duplicate licence. + + * imap/mailimap_keywords.[ch] + * imap/mailimap_sender.[ch] + * imap/mailimap_socket.[ch] + * imap/mailimap_ssl.[ch] + * imf/mailimf.[ch] + * imf/mailimf_types.[ch] + * imf/mailimf_write.[ch] + * maildir/maildir.[ch] + * mbox/mailmbox.[ch] + * mbox/mailmbox_types.[ch] + * mime/mailmime.[ch] + * mime/mailmime_content.[ch] + * mime/mailmime_decode.[ch] + * mime/mailmime_disposition.[ch] + * mime/mailmime_types.[ch] + * mime/mailmime_types_helper.[ch] + * mime/mailmime_write.[ch] + * nntp/newsnntp.[ch] + * nntp/newsnntp_socket.[ch] + * nntp/newsnntp_ssl.[ch] + * pop3/mailpop3.[ch] + * pop3/mailpop3_socket.[ch] + * pop3/mailpop3_ssl.[ch] + * smtp/mailsmtp.[ch] + * smtp/mailsmtp_helper.[ch] + * smtp/mailsmtp_socket.[ch] + * smtp/mailsmtp_ssl.[ch] + * tools/charconv.[ch] + * tools/chash.c + * tools/connect.[ch] + * tools/mail_cache_db.[ch] + * tools/maillock.[ch] + * tools/mailstream.[ch] + * tools/mailstream_helper.[ch] + * tools/mailstream_low.[ch] + * tools/mailstream_socket.c + * tools/mailstream_ssl.c + * tools/mailstream_types.h + applied 'const' qualifier where it is needed except in + generic part. + +2003-12-03 - libetpan-0.30-cvs16 - hoa + + * imap/mailimap_sender.c + Workaround for a bug in Courier-IMAP. + Thanks to Mark B. Elrod. + +2003-12-03 - libetpan-0.30-cvs15 - hoa + + * README + * imap/mailimap_sender.c + fixed IMAP protocol when sending a DELETE command + (there was a missing space). + Thanks to Zsolt VARGA. + +2003-12-02 - libetpan-0.30-cvs14 - hoa + + * generic/maildriver_types.h + * generic/maildriver_tools.c + * generic/nntpdriver.c + * generic/nntpdriver_cached.c + * tests/frm-simple.c + * tests/frm.c + changed semantic of get_envelopes_list() : + the messages that could not be fetched are not + removed from the given list. + +2003-12-02 - libetpan-0.30-cvs13 - hoa + + * tests/Makefile + * tests/compose-msg.c + * tests/etpan-message-data-driver.[ch] * REMOVED FILES * + * tests/fetch-attachment.c + * tests/frm-common.c * NEW FILES * + * tests/frm-simple.c + * tests/frm-tree.c + * tests/frm.c + * tests/readmsg-common.c + * tests/readmsg.c + synchronize tests with new API. + +2003-12-02 - libetpan-0.30-cvs12 - hoa + + * generic/mboxdriver.c + * generic/mboxdriver_cached.c + * generic/mboxdriver_cached_message.c + * generic/mboxdriver_message.c + * generic/mboxdriver_tools.c + * mbox/mailmbox.c + * mbox/mailmbox_parse.c + * mbox/mailmbox_types.[ch] + added a prefix before field names in mbox module. + +2003-12-02 - libetpan-0.30-cvs11 - hoa + + * generic/imapdriver_tools.c + * generic/imfcache.c + * generic/maildriver_types.c + * generic/mailthread.c + * imf/mailimf.c + * imf/mailimf_types.[ch] + * imf/mailimf_types_helper.c + * imf/mailimf_write.c + * mime/mailmime.c + * mime/mailmime_content.c + added a prefix before field names in IMF module. + +2003-12-01 - libetpan-0.30-cvs10 - hoa + + * generic/maildirdriver.c + * generic/maildirdriver_cached.c + * generic/maildirdriver_tools.c + * generic/mhdriver.c + * generic/mhdriver_cached.c + * generic/mhdriver_cached_message.c + * generic/mhdriver_message.c + * generic/mhdriver_tools.c + * maildir/maildir.c + * maildir/maildir_types.h + * mh/mailmh.c + * mh/mailmh.h + added a prefix before field names in MH + and maildir modules. + Thanks to Melvin Hadasht. + +2003-12-01 - libetpan-0.30-cvs9 - hoa + + * generic/nntpdriver.c + * generic/nntpdriver_cached.c + * generic/nntpdriver_tools.c + * generic/pop3driver.c + * generic/pop3driver_cached.c + * generic/pop3driver_cached_message.c + * generic/pop3driver_tools.c + * nntp/newsnntp.[ch] + * nntp/newsnntp_types.h + * pop3/mailpop3.[ch] + * pop3/mailpop3_types.h + added a prefix before field names in NNTP + and POP3 modules. + Thanks to Melvin Hadasht. + +2003-12-01 - libetpan-0.30-cvs8 - hoa + + * generic/imapdriver_cached_message.c + * generic/imapdriver_message.c + * generic/imapdriver_tools.c + * generic/mailmessage_tools.c + * generic/mime_message_driver.c + * mime/mailmime_content.c + * mime/mailmime_decode.c + * mime/mailmime_disposition.c + * mime/mailmime_types.[ch] + * mime/mailmime_types_helper.[ch] + * mime/mailmime_write.c + changed field name in MIME module and + replaced some structure with union. + + * imap/mailimap.c + * nntp/newsnntp.c + fixed bug that didn't allow connection. + +2003-12-01 - libetpan-0.30-cvs7 - hoa + + * libetpan-config.in + added LDFLAGS to libetpan-config --libs. + + * nntp/newsnntp.c + * pop3/mailpop3.c + * generic/mailstorage_tools.c + don't unreference stream on connect() error. + + * generic/data_message_driver.c + * generic/maildriver_types.c + * generic/maildriver_types.h + * generic/mailmessage_tools.c + now a zero length string can be given as (NULL, 0) + for the content of the message. + changed field names of mail_search_key structure. + + * generic/maildriver_errors.h + added error type. + + * generic/imapdriver.c + * generic/imapdriver_cached.c + * generic/imapdriver_cached_message.c + * generic/imapdriver_message.c + * generic/imapdriver_tools.c + * generic/nntpdriver_message.c + * imap/mailimap.c + * imap/mailimap.h + * imap/mailimap_helper.c + * imap/mailimap_print.c + * imap/mailimap_sender.c + * imap/mailimap_socket.c + * imap/mailimap_types.[ch] + * imap/mailimap_types_helper.[ch] + changed the name of the fields in IMAP low-level implementation, + (prefix has been added to field names in structures). + + * mime/mailmime.c + a FWS can now appear in Content-Type field, before + the MIME type. + +2003-11-25 - libetpan-0.30-cvs6 - hoa + + * generic/mboxdriver_cached.c + max-uid file is now located in flags directory. + this allows to keep flags coherence. + +2003-11-25 - libetpan-0.30-cvs5 - hoa + + * configure.in + * tools/mailstream_socket.c + * tools/mailstream_ssl.c + removed specific check for <sys/select.h> + + * generic/data_message_driver.c + * generic/data_message_driver.h + * generic/libetpan_version.h.in + * generic/maildriver_errors.h + * generic/mime_message_driver.c + * generic/mime_message_driver.h + added licence information. + +2003-11-25 - libetpan-0.30-cvs4 - hoa + + * configure.in + * tools/mailstream_socket.c + * tools/mailstream_ssl.c + Check for valid <sys/select.h>. + Because Mac OS X systems, <sys/select.h> cannot be included + alone. Then, we follow the old standard to use select() system + call. + + * generic/generic_cache.c + * generic/libetpan_version.c + clean up code. + + * tools/mail_cache_db.c + Support for Berkeley DB version 1.x. + +2003-11-25 - libetpan-0.30-cvs3 - hoa + + * generic/maildirdriver.c + fixed a crash in get_envelopes_list(). + + * generic/maildriver_errors.h * NEW FILE * + * generic/maildriver_types.h + moved error codes from maildriver_types.h to + maidlriver_errors.h. + + * generic/mailthread.h + * generic/mailthread_types.h + moved threading type to mailthread_types.h + + * maildir/maildir.c + added internal basename() function so that + libEtPan! can compile on Mac OS X. + + * tools/mail_cache_db.c + * tools/maildb_helper.[ch] * REMOVED FILES * + added support for DB1 (cleanse of database) and + removed deprecated files. + +2003-11-22 - libetpan-0.30-cvs2 - hoa + + * generic/nntpdriver_message.c + added UID to NNTP mailmessage structure. + +2003-11-22 - libetpan-0.30-cvs1 - hoa + + * generic/imapdriver.c + * generic/imapdriver_cached.c + * generic/imapdriver_message.c + * generic/imapdriver_tools.c + * generic/maildirdriver.c + * generic/maildirdriver_cached.c + * generic/maildriver.[ch] + * generic/maildriver_types.h + * generic/mboxdriver.c + * generic/mboxdriver_cached.c + * generic/mboxdriver_message.c + * generic/mhdriver.c + * generic/mhdriver_cached.c + * generic/mhdriver_message.c + * generic/nntpdriver.c + * generic/nntpdriver_cached.c + * generic/pop3driver.c + * generic/pop3driver_cached.c + mailsession_get_message_by_uid() is added. + It is used like mailsession_get_message(), + but using the uid string. + This is implemented in imap driver, nntp driver, + mh driver and mbox driver (cached and non cached version). + This is not implemented in pop3 nor maildir. + + uid member of mailmessage structure is always defined for + drivers where this function is implemented. + + Thanks to Melvin Hadasht. + +2003-11-21 - libetpan-0.30 - hoa + + * release 0.30 - Spock's Beard release + + * general + - fixed several memory leaks. + + - defines now exist for new features since version 0.29 + + * tools + - dump of network traffic is now possible by setting + exported variable mailstream_debug to 1. + + - TLS/SSL driver for stream is fixed. + + * imf + - fixed RFC 2822 format, wrap headers and break lines + when they are longer than requirement (998). + + - reduced size of headers data. + a union is used inside the structure. + *** WARNING *** : this change use of structure field as a union + member is used in mailimf_field structure. + + * imap + - several fixes in IMAP module. + + * mime + - fixed quoted-printable parser. + + * generic - cache for drivers + - cache database is now cleaned up. + + - fixed header fields cache. + *** WARNING *** cache format changed. You should reset all + your cache of headers (env.db). + + * generic - threading + + - fixed threading when threading by references with subject. + + * generic - drivers for message + + - separated flush() and check() in message. + *** WARNING *** : this changes the API of the message. + flush() is used to free the internal structure used + to store the MIME structure of the message. It invalidates + the "mime" member of the message. + check() is used for to notify the modification of message + flags to the session, so that the session saves the flags + of the message at the next call of mailsession_check() or + when leaving the session. + + - IMAP implementation is more compliant. + + - added driver to build MIME message and see the rendering + through fetch functions. + + - added driver to parse message content given with a string. + + * generic - drivers for maildir + + - maildir driver for storage / session / messages + is implemented. + +2003-11-21 - libetpan-0.1-cvs31 - hoa + + * Makefile.in + * README + * configure.in + * generic/Makefile + * generic/libetpan.h + * generic/libetpan_version.c + * generic/libetpan_version.h.in + support for runtime version of libetpan + +2003-11-20 - libetpan-0.29-cvs30 - hoa + + * imf/mailimf_write.c + wrap mailbox list when we have a single address as + a mailbox. + +2003-11-20 - libetpan-0.29-cvs29 - hoa + + * generic/imapdriver.c + clean up code. + + * imap/mailimap.c + update message count with EXPUNGE responses. + + * tools/mailstream_socket.c + added comment about initial state of socket. + + * tools/mailstream_ssl.c + added comment about initial state of socket. + read() is fixed. + +2003-11-19 - libetpan-0.29-cvs28 - hoa + + * generic/mailthread.c + fixed threading by references when using subjects. + +2003-11-19 - libetpan-0.29-cvs27 - hoa + + * generic/maildirdriver_cached.c + * generic/mboxdriver_cached.c + * generic/mhdriver_cached.c + * generic/nntpdriver_cached.c + * generic/pop3driver_cached.c + don't open any files if flags_store is empty. + + * imap/mailimap_types.c + fixed a crash when freeing a mailbox list information + with no flags. + + * tools/mailstream.c + default value for network timeout. + +2003-11-17 - libetpan-0.29-cvs26 - hoa + + * imap/mailimap.c + * imap/mailimap_sender.c + fixed syntax of SEARCH command. + + * tools/mailstream.[ch] + * tools/mailstream_types.h + if LIBETPAN_STREAM_DEBUG is define in mailstream_types.h, we + can use a global variable mailstream_debug to enable the dump + of the network protocol on the file libetpan-stream-debug.log. + +2003-11-17 - libetpan-0.29-cvs25 - hoa + + * generic/imapdriver.c + use SEARCH instead of STATUS on selected folder to + get UNSEEN messages count. + + * imap/mailimap.c + allows multiple SEARCH responses. + + * imap/mailimap_keywords.c + * imap/mailimap_parser.c + fixed parsing of mailbox flags. + + * tools/clist.c + fixed count when using clist_concat(). + +2003-11-14 - libetpan-0.29-cvs24 - hoa + + * imf/mailimf_write.c + fixed the space between Message-IDs, problem introduced + by rewriting of headers wrapper. + +2003-11-13 - libetpan-0.29-cvs23 - hoa + + * generic/maildirdriver_types.h + * generic/mhdriver_types.h + fixed some comments. + + * mime/mailmime_content.c + fixed infinite loop in MIME parser. + +2003-11-12 - libetpan-0.29-cvs22 - hoa + + * generic/maildriver_tools.h + removed exported functions that does no more exist. + +2003-11-12 - libetpan-0.29-cvs21 - hoa + + * generic/maildriver_tools.h + removed exported function that does no more exist. + +2003-11-11 - libetpan-0.29-cvs20 - hoa + + * generic/Makefile + * generic/mailmessage.h + * generic/data_message_driver.[ch] * NEW FILES * + * generic/mime_message_driver.[ch] * NEW FILES * + driver to allow construction of MIME message. + (mime_message_driver.[ch]). + driver to operations on message which content is + given by a string. + +2003-11-10 - libetpan-0.29-cvs19 - hoa + + * Makefile.in + compilation of maildir low-level implementation. + + * maildir/Makefile * NEW FILE * + * maildir/maildir.[ch] * NEW FILES * + * maildir/maildir_types.h * NEW FILE * + maildir low-level implementation. + + * generic/Makefile + * generic/maildirdriver.[ch] * NEW FILES * + * generic/maildirdriver_cached.[ch] * NEW FILES * + * generic/maildirdriver_cached_message.[ch] * NEW FILES * + * generic/maildirdriver_message.[ch] * NEW FILES * + * generic/maildirdriver_tools.[ch] * NEW FILES * + * generic/maildirdriver_types.h * NEW FILE * + * generic/maildirstorage.[ch] * NEW FILES * + implementation of maildir driver, cached and non-cached + versions. + + * generic/generic_cache.c + use msync() when finished writing using mmap() with MAP_SHARED. + + * generic/imapdriver_tools.c + changed flag name "Forwarded" into something more standard + "$Forwarded" (draft on flag keywords for IMAP). + + * generic/maildriver.h + added maildir drivers for session. + + * generic/maildriver_types.h + * generic/mailmessage_tools.c + added message data for drivers that will use internal + data although they are using the generic functions. + + * generic/mailmessage.h + added maildir drivers for message. + + * generic/mailstorage.h + added maildir driver for storage. + + * generic/mboxdriver_cached.c + optimization on memory use. + + * generic/mhdriver_cached.c + code clean up. + + * generic/mhdriver_tools.c + * mh/mailmh.c + don't use MAP_SHARED for mmap() where it is not needed. + + * tests/fetch-attachment.c + * tests/frm.c + * tests/frm-simple.c + * tests/frm-tree.c + * tests/frm.c + * tests/option-parser.[ch] + * tests/readmsg-simple.c + * tests/readmsg.c + factorize code of storage initialization into + option-parser.[ch]. + +2003-11-09 - libetpan-0.29-cvs18 - hoa + + * generic/imapdriver_tools.c + fixed management of MAIL_FLAG_FORWARDED. + + * generic/nntpdriver_tools.c + fixed a memory leak. + + * imap/mailimap_types.c + fixed a memory freeing. + +2003-11-05 - libetpan-0.29-cvs17 - hoa + + * imf/mailimf.c + broken parsing of message-id due to previous change + is fixed. + +2003-11-05 - libetpan-0.29-cvs16 - hoa + + * imf/mailimf.c + accept some weird syntax, for example : + foo@bar.com <foo@bar.com> + This is now accepted. + +2003-11-04 - libetpan-0.29-cvs15 - hoa + + * imf/mailimf_write.c + fixed (again) wrapping of header fields. + +2003-11-03 - libetpan-0.29-cvs14 - hoa + + * generic/imapdriver_message.c + fixed behaviour of IMAP message driver. + +2003-11-03 - libetpan-0.29-cvs13 - hoa + + * mh/mailmh.[ch] + * mime/mailmime.[ch] + * mime/mailmime_decode.[ch] + * mime/mailmime_disposition.[ch] + * mime/mailmime_types.[ch] + * mime/mailmime_types_helper.[ch] + removed duplicated licence. + + * mime/mailmime_content.[ch] + * mime/mailmime_write.[ch] + removed duplicated licence. + fixed quoted-printable parser. + fixed multipart parser, preamble and epilogue are now stored. + fixed quoted-printable part renderer. + +2003-10-29 - libetpan-0.29-cvs12 - hoa + + * generic/mailmessage_tools.c + fixed a bug in generic fetch header part of section. + + * generic/nntpdriver.c + check() replace flush() message in message envelopes list + fetch to reflect new API (0.29-cvs1). + +2003-10-29 - libetpan-0.29-cvs11 - hoa + + * imf/mailimf_write.c + workaround for a bug of old versions of INN. + + * mime/mailmime_types_helper.c + mailmime_single_fields_init() now accept NULL as the + "mailmime_fields" argument, so that we call this function + with only a "mailmime_content". + +2003-10-29 - libetpan-0.29-cvs10 - hoa + + * generic/imapdriver_cached.c + * generic/imapdriver_cached_message.c + * generic/mboxdriver_cached.c + * generic/mhdriver_cached.c + * generic/nntpdriver_cached.c + * generic/pop3driver_cached.c + code cleanup. + message content cache files are now cleaned up in + an unlocked state. + +2003-10-29 - libetpan-0.29-cvs9 - hoa + + * mbox/mailmbox.c + fixed get_line() function. Does not get out from the buffer. + +2003-10-29 - libetpan-0.29-cvs8 - hoa + + * generic/imapdriver_tools.c + fixed conversion of data in IMAP driver. + +2003-10-29 - libetpan-0.29-cvs7 - hoa + + * mime/mailmime_content.c + remove unparsed IMF (RFC 2822) headers in the + parsed MIME structure, that are MIME headers, + so that rendering of MIME message from parsed MIME + structure is correct. + +2003-10-28 - libetpan-0.29-cvs6 - hoa + + * generic/nntpdriver_cached.c + now, the flags are not lost when the cache is deleted. + + * generic/imapdriver_message.c + get rid of deprecated things in IMAP protocol. + mailmessage_fetch() will no longer mark the message + as read. + +2003-10-28 - libetpan-0.29-cvs5 - hoa + + * generic/imfcache.c + fixed header fields cache. + *** WARNING *** cache format changed. You should reset all + your cache of headers (env.db). + + * generic/maildriver.h + added comment about driver function. + + * tools/maillock.c + change dotlock behaviour (wait 5 seconds after each failed try) + +2003-10-27 - libetpan-0.29-cvs4 - hoa + + * README + added information about C #define + + * generic/imapdriver_cached_message.c + fixed memory leak in cached IMAP message driver. + MIME structure is not fetched again when already fetched. + + * imf/mailimf_types.h + added LIBETPAN_MAILIMF_FIELD_UNION #define to know that + we are on version of libEtPan! with a union to implement + mailimf_field data type. + + * generic/maildriver_types.h + added LIBETPAN_MAILMESSAGE_CHECK #define to know that + we are on version of libEtPan! with mailmessage_check() + call separated from mailmessage_flush() call, introduced + in 0.29-cvs1 + + * imf/mailimf_write.c + fixed wrapping of header text. First character was removed + when the first word was too long. + + * generic/generic_cache.[ch] + * generic/generic_cache_types.h + * generic/imapdriver.[ch] + * generic/imapdriver_cached.[ch] + * generic/imapdriver_tools.h + * generic/imapdriver_types.h + * generic/imapstorage.[ch] + * generic/imfcache.[ch] + * generic/libetpan.h + * generic/maildriver.c + * generic/maildriver_tools.c + * generic/maildriver_types.c + * generic/mailmessage_types.h + * generic/mailstorage.[ch] + * generic/mailstorage_tools.[ch] + * generic/mailstorage_types.h + * generic/mboxdriver.[ch] + * generic/mboxdriver_cached.h + * generic/mboxdriver_types.h + * generic/mboxstorage.[ch] + * generic/mhdriver.[ch] + * generic/mhdriver_cached.[ch] + * generic/mhdriver_types.h + * generic/mhstorage.[ch] + * generic/nntpdriver.[ch] + * generic/nntpdriver_cached.[ch] + * generic/nntpdriver_types.h + * generic/nntpstorage.[ch] + * generic/pop3driver.[ch] + * generic/pop3driver_cached.[ch] + * generic/pop3driver_types.h + * generic/pop3storage.[ch] + * imap/mailimap_types_helper.[ch] + * imf/mailimf_types_helper.h + * imf/mailimf_write.h + * mbox/mailmbox.h + * mh/mailmh.[ch] + * mime/mailmime.[ch] + * mime/mailmime_content.[ch] + * mime/mailmime_decode.[ch] + * mime/mailmime_disposition.[ch] + * mime/mailmime_types.[ch] + * mime/mailmime_types_helper.[ch] + * mime/mailmime_write.[ch] + * tools/carray.[ch] + * tools/charconv.[ch] + * tools/chash.[ch] + * tools/cinthash.[ch] + * tools/clist.[ch] + * tools/hmac-md5.h + * tools/mailstream_socket.h + * tools/mailstream_types.h + * tools/mapping.[ch] + * tools/md5.[ch] + * tools/md5global.h + * tools/mmapstring.[ch] + added licence information and name of last commiter. + +2003-10-25 + + * version 0.29-cvs3 + * generic/imapdriver_cached.c + fixed wrong message size (of 0) when UID list cache is + used in IMAP cached driver. The size is now stored in the + UID list cache. + + * imf/mailimf.c + fixed single address parsing (his will strip all spaces in + the address) + +2003-10-24 + + * version 0.29-cvs2 + * generic/imapdriver_tools.c + flag NEW in IMAP driver is disabled when the message is SEEN. + +2003-10-23 + + * version 0.29-cvs1 + * imf - reduced size of headers data + WARNING : this change use of structure field as a union + member is used in mailimf_field structure. + * generic - imap - fixed some data conversion + * tools - chash - add a call + * generic - separated flush() and check() in message. + WARNING : this changes the API of the message. + flush() is used to free the internal structure used + to store the MIME structure of the message. It invalidates + the "mime" member of the message. + check() is used for to notify the modification of message + flags to the session, so that the session saves the flags + of the message at the next call of mailsession_check() or + when leaving the session. + * all - fixed some leaks + * imf - fixed mailbox group parsing + * imf, mime - fixed RFC 2822 format (CR LF at end of lines) + * generic - pop3, nntp - fixed memory leaks + * generic - message theading - waste less memory + * imap - fixed some memory leaks + * mime - parse some non-conform MIME encoded headers + * nntp - fixed a memory leak + * mbox - strip UID headers when fetching message content + * tools - adds new database cache file interface (mail_cache_db.[ch]) + * tools - added extern "C" { } to avoid name mangling in C++ + * generic - drivers now make use of new database cache file interface. + * tools - adds a function to clean up the database file + * all - some compilation warning fixes + * generic - drivers - cached drivers now clean their cache + * mbox - removed use of cinthash + * generic - mbox - removed use of cinthash + * all - removed use of alloc.h + * imf - can now fold some more headers (including headers with free + form values) for more standards conformance + * mime - can parse multilines headers, fixed quoted-printable + decoding (all single \n are now decoded to \r\n) + * mbox - synchronize mmapped file before unmapping it. + * tools - mmapstring - removed use of cinthash, replaced with chash + +2003-10-06 - XetPan release + + * version 0.29 + * generic - imap - bugfixes + * tools - mailstream - debug for stream, network timeout + * tools - mailstream - ssl library is initialized by ssl driver, + fixed a bug + * tools - chash - fixed chash interface + * imf - fixed interface + * mime - fixed memory leak and some interface + * generic - fixed messages thread + * nntp - bugfixes + * pop3 - bugfixes + * smtp - added SMTP auth CRAM-MD5, LOGIN, PLAIN + * imap - bugfixes + * mime - fixed writing of MIME part + * tests - added SMTP sample, thanks to Gael Roualland + +2003-04-01 - Avril Lavigne Release + + * version 0.28 + * imap - fixed IMAP parser + * mime - fixed section id generation + * mime - fixed mime parser + * generic - conform to IMAP naming for flags + * tools - prefix for tcp_connect() and get_service_port() + * generic - nntp - noop function added + * configure - some fixes + * generic - message parse fixes + * generic - nntp - non existant message are marked as read + * generic - thanks to David Woodhouse, access to protocol + using a command, (ex: ssh /usr/sbin/imapd) + imply an API change when calling nntp_storage_init(), + pop3_storage_init() or imap_storage_init(). + * generic - pop3 - apop is tried and if deconnected, reconnection + is carried out and clear authentication is tried. + * mime - make public the encoding functions + * mime - conform to RFC 2046 (quoted-string) + * tools - fixed chash + +2002-12-18 - Christmas release ^^ //clindoeil + + * version 0.27 + * imf - added easier interface for IMF fields (RFC 2822) + * mime - added easier interface for MIME fields + * mime - conversion to quoted printable will quote F to avoid + "From_" sequence + * imf - easier usage of IMF (RFC 2822) + * fixed toupper() usage + * generic - changed interface for mail threading so that we + can notify a default charset. + * sunZ - capitaine de soir�es + * tools - charconv can convert strings with illegal sequences + * mime - add helper functions + * imf - add helper functions + * various bugfixes + * imap - comments in IMAP module - API and data structure description + * generic - API documentation + * generic - flags and cache directory are now different + * all - can be used in C++ + * doc - updated documentation + +2002-09-02 + + * version 0.26 + * generic - message interface + * - new driver interface + * imf - bugfix + * generic - generic flags, flags for all drivers + * generic - mail_info (display of the messages list) + and mailmessage (display of the message) merged + * tools - fixed an infinite loop when EOF was reached when + fetching a line finished with LF. + * mime - does not parse the message mime part when the subtype is + not RFC822 + * generic - flags and envelopes are stored into Berkeley Database + for performance + * generic - Berkeley database are now locked (with dotlock) + * generic - expunge for mboxdriver (cached version). + * tools - bugfix in chash + * mh - make a hash table from the subfolders + * generic - expunge for pop3driver and mhdriver (cached version) + * generic - status of mailboxes + * generic - fixed a problem with cache in mbox + * generic - fixed cache for nntp driver + * generic - "References" field is now fetched with IMAP driver + * imap - bugfix when parsing HEADER.FIELDS requests + bugfix in literal + * generic - readonly mailbox in mbox driver are no more expunged + * tools - fixed memory leaks + * generic - internal uid of mbox is based on body length of the message + close mailboxes when retrieving non-cached envelopes. + * generic - optimized flags cache + * generic - mail storage added + * generic - check_folder will store flags on disk + * imap - close stream no session logout + * imf - day of week stuff + * mh - implemented ...folder_find + * tools - some code factorization in clist + * imap - bugfix for mailbox data and status attribute (UNSEEN) handler + +2002-06-26 + + * version 0.25 + * BSD licence + * get rid of strndup() + * generic - started implementation of messages threads + * driver - changed the way to get message list in NNTP driver + fetch message returns also the length of the message + bug fix in IMAP driver + * MIME - MIME message builder use the same data structure + as the MIME message parser + * imf - less strict parser, bug fix + * nntp - bugfix + * mbox - UID in mbox + * pop - capa is implemented + * driver - cache for mbox and mh, new version of the driver + of mbox. + * mh - max index is retrieved when performing a stat of the folder + * MIME - bugfix when parsing multipart, base64 at padding + encoded phrase can now be parsed + * tools - character table conversion for buffers + * generic - implementation of message threads in now finished + * tools - character table conversion notify error type + * mime - merged mailmime_write.c and message_build.c + * driver - changed interface when fetching MIME parts + * driver - error strings added + * generic - thread orderedsubject is implemented + * mbox - problem when the message identifier was wrong - fixed + * mh - added time information so that the mh-cached driver + can invalidate the cache + * driver - MH driver with cache is implemented + * mime - add parent in mailmime structure + * tools - macro fixed in carray + * imap - imap debugging can now compile + * driver - added parameters() to interface to set parameters specific + to each driver. + cache is now defined for each session, no more globally. + some code cleaning + mbox parameters are "force read only" and "force no UID" + nntp set max articles to fetch + * all - changed <stdint.h> to <inttypes.h> which is more widespread + * pop3 - fixed APOP, timestamp is get at connection, no more when + APOP was tried. + * tools - GPL MD5 is replaced by RSA Data Security MD5. + * driver - nntp cache sets starting and ending article in the cache + mbox cache for a message is updated when it is changed + (detected with size) + * tools - changed the name of stream driver so that it does + not interfer with pth. + the user is given the responsibility to initialize the + SSL mechanism (openssl). + * mime - serious bugfix + * imf - removed "unparsed fields" type. + * driver - nntp does not use xover whenever there are no news + header to fetch + bugfix in imap + take account of the bugfix in mime in maildriver_tools.c + no more use of "unparsed fields". + +2002-04-27 + + * version 0.20 + * glib calls removed + * driver interface added + +2002-02-10 + + * version 0.10 + * initial release Added: freeswitch/trunk/libs/libetpan/INSTALL ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/INSTALL Wed Dec 20 15:28:56 2006 @@ -0,0 +1,183 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + Added: freeswitch/trunk/libs/libetpan/Makefile.in ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/Makefile.in Wed Dec 20 15:28:56 2006 @@ -0,0 +1,109 @@ +# Main makefile + +srcdir = @srcdir@ +top_builddir = . +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ +includedir = @includedir@ +mandir = @mandir@ +bindir = @bindir@ +SHELL = /bin/sh +RM = rm -fr +INSTALL = @INSTALL@ +LIBTOOL = @LIBTOOL@ +@SET_MAKE@ + +#SUBDIRS = imap nntp pop3 smtp tools imf mbox mh maildir mime generic +#SUBLIBS = imap/libmailimap.la nntp/libnewsnntp.la pop3/libmailpop3.la \ +# smtp/libmailsmtp.la tools/libtools.la imf/libmailimf.la \ +# mbox/libmailmbox.la mh/libmailmh.la mime/libmailmime.la \ +# maildir/libmaildir.la generic/libmaildriver.la + +SUBDIRS = src + +#TARGET = libetpan.la +#VERSINFO = @API_VERSION@ +#CC = @CC@ +#LDFLAGS = @LIBS@ @SSLLIBS@ @LDFLAGS@ @DBLIB@ +CPP = @CPP@ + +all: config-files prepare all-recursive + +distclean: clean distclean-recursive + $(RM) config.h config.cache config.log config.status \ + Makefile Rules *~ gmon.out *.bak core libtool \ + libetpan-config src/main/libetpan_version.h \ + libetpan-config.h + +maintainer-clean: distclean + $(RM) configure config.h.in aclocal.m4 config.guess config.sub ltmain.sh autom4te.cache + +realclean: maintainer-clean + +all-recursive install-recursive clean-recursive \ + distclean-recursive prepare-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + target=`echo $@ | sed s/-recursive//`; \ + echo "Making $$target in $$subdir"; \ + (cd $$subdir && $(MAKE) $$target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" + +install: all install-dirs install-recursive + $(INSTALL) -m 755 libetpan-config $(DESTDIR)$(bindir) + $(INSTALL) -m 644 libetpan-config.h $(DESTDIR)$(includedir)/libetpan + $(INSTALL) -m 644 src/main/libetpan.h $(DESTDIR)$(includedir) + +install-dirs: + $(INSTALL) -d -m 755 $(DESTDIR)$(includedir) + $(INSTALL) -d -m 755 $(DESTDIR)$(includedir)/libetpan + $(INSTALL) -d -m 755 $(DESTDIR)$(bindir) + +#realclean: maintainer-clean + +clean: clean-recursive + $(RM) $(TARGET) .libs $(top_builddir)/include libetpan-config.h + +test: + +#$(TARGET): config-files $(SUBLIBS) +# $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ $(SUBLIBS) \ +# -rpath $(libdir) -version-info $(VERSINFO) + +#$(SUBLIBS): all-recursive + +libetpan-config.h: $(srcdir)/libetpan-config.h.in + cp $(srcdir)/libetpan-config.h.in libetpan-config-in.h + $(CPP) -I$(srcdir) libetpan-config-in.h | sed -e '/^#/d;/^[ \t]*$$/d;s/^@/#/' > libetpan-config.h + $(RM) -f libetpan-config-in.h + +prepare: prepare-recursive libetpan-config.h + mkdir -p ${top_builddir}/include/libetpan + cp -f libetpan-config.h $(top_builddir)/include/libetpan + +# config files +config-files: ${srcdir}/configure ${srcdir}/config.h.in Makefile config.status Rules ${srcdir}/src/Makefile + +${srcdir}/configure: configure.in + cd ${srcdir} && aclocal && autoconf + +${srcdir}/config.h.in: configure.in + rm -f ${srcdir}/config.h.in && cd ${srcdir} && autoheader + +Makefile: Makefile.in config.status + cd ${top_builddir} && CONFIG_FILES=Makefile CONFIG_HEADERS= ./config.status + +${srcdir}/src/Makefile : ${srcdir}/src/Makefile.in config.status + cd ${top_builddir} && CONFIG_FILES=src/Makefile CONFIG_HEADERS= ./config.status + +#${srcdir}/src/low-level/Makefile : ${srcdir}/src/low-level/Makefile.in config.status +# cd ${top_builddir} && CONFIG_FILES=src/low-level/Makefile CONFIG_HEADERS= ./config.status + +Rules: Rules.in config.status + cd ${top_builddir} && CONFIG_FILES=Rules CONFIG_HEADERS= ./config.status + +config.status: configure + ./config.status --recheck + Added: freeswitch/trunk/libs/libetpan/NEWS ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/NEWS Wed Dec 20 15:28:56 2006 @@ -0,0 +1,284 @@ +2006-03-22 - libetpan-0.45 + + * release 0.45 - Depth Charge + bugfix release + +2006-03-08 - libetpan-0.43 + + * release 0.43 - Lateralus + bugfix release + +2006-01-09 - libetpan-0.42 + + * release 0.41 - Figure Number Five + bugfix release + +2005-12-02 - libetpan-0.41 + + * release 0.41 - Transfixion + * passphrase is implemented for S/MIME and PGP. + * avoid symbols conflict between GnuTLS and OpenSSL. + +2005-10-07 - libetpan-0.40 - hoa + + * release 0.40 - Kashmir + + * SSL initialization is optional. + +2005-09-16 - libetpan-0.39 - hoa + + * release 0.39 - Deliverance + + * compatibility with GnuTLS + * SASL for higher level + +2005-07-20 - libetpan-0.38 - hoa + + * release 0.38 - Deadwing + + * fixed SSL + * IMAP improvements + * SASL + +2005-07-03 - libetpan-0.37 - hoa + + * release 0.37 - Deadwing + + * windows port + * fixed IMAP implementation (for sylpheed) + +2005-02-22 - libetpan-0.36 - hoa + + * release 0.36 - Silver Drop + + * memory leak + * fixed maildir support + +2004-12-28 - libetpan-0.35 - hoa + + libEtPan! - a mail library + + * release 0.35 - Dimebag Darrell + + * minor bugfixes. + +2004-11-04 - libetpan-0.34 - hoa + + libEtPan! - a mail library + + * release 0.34 - edge + + * general + - support for debian systems mbox + - ability to disable thread-safe support + + +2004-08-24 - libetpan-0.33 - hoa + + libEtPan! - a mail library + + * release 0.33 - entropia + + * general + - bugfixes in IMAP module and mailstream + - fixed low-level data structures + - better support for ARM and PPC architecture + - support for cross-compilation + - fixed Berkeley DB support + - changed folder structure of libetpan package + - can now add a message to a mailbox with flags + - support for hotmail mailboxes (with help of hotwayd) + - added Berkeley DB mail storage as experimental + - added support for PGP and S/MIME + - better folder API + + +2003-12-16 - libetpan-0.32 - hoa + + libEtPan! - a mail library + + * release 0.32 - Black Utopia + + * general + - added documentation for IMF / tools + - bugfixes in IMAP module due to structures change. + - Application that use libEtPan! now have to use + '#include <libetpan/libetpan.h>' + + * generic + - get_message() is implemented in Maildir cached driver. + +2003-12-10 - libEtPan! version 0.31 + + libEtPan! - a mail library + + * release 0.31 - Steve Morse release + + * general + - all fields name of structures are changed. + - bugfixes. + - union {} are added everywhere it is possible to save memory. + - support for Berkeley DB 1. + - improved compatibility with FreeBSD and Mac OS X. + + * drivers + - cache drivers are disable if Berkeley DB is not found. + - disable search call. + - support of buggy Courier-IMAP server. + - semantic of mailsession_get_envelopes_list() changed : it + does no more remove messages from the list. + - mailsession_get_message_by_uid() is added and implemented + in some drivers. + +2003-11-21 - libEtPan! version 0.30 + + libEtPan! - a mail library + + * release 0.30 - Spock's Beard release + + * main new features + - cache for drivers is cleaned up. + - maildir driver. + + * general + - fixed several memory leaks. + + - defines now exist for new features since version 0.29 + + + * tools + - dump of network traffic is now possible by setting + exported variable mailstream_debug to 1. + + - TLS/SSL driver for stream is fixed. + + * imf + - fixed RFC 2822 format, wrap headers and break lines + when they are longer than requirement (998). + + - reduced size of headers data. + a union is used inside the structure. + *** WARNING *** : this change use of structure field as a union + member is used in mailimf_field structure. + + * imap + - several fixes in IMAP module. + + * mime + - fixed quoted-printable parser. + + * generic - cache for drivers + - cache database is now cleaned up. + + - fixed header fields cache. + *** WARNING *** cache format changed. You should reset all + your cache of headers (env.db). + + * generic - threading + + - fixed threading when threading by references with subject. + + * generic - drivers for message + + - separated flush() and check() in message. + *** WARNING *** : this changes the API of the message. + flush() is used to free the internal structure used + to store the MIME structure of the message. It invalidates + the "mime" member of the message. + check() is used for to notify the modification of message + flags to the session, so that the session saves the flags + of the message at the next call of mailsession_check() or + when leaving the session. + + - IMAP implementation is more compliant. + + - added driver to build MIME message and see the rendering + through fetch functions. + + - added driver to parse message content given with a string. + + * generic - drivers for maildir + + - maildir driver for storage / session / messages + is implemented. + +* 2003-10-06 - libEtPan! version 0.29 + + libEtPan! - a mail library + + * XetPan release + + * debug for stream, network timeout + * SSL library is initialized by SSL stream driver + * fixed messages threading + * added SMTP authentication CRAM-MD5, LOGIN, PLAIN + * added example of use of SMTP + +* 2003-04-01 - libEtPan! version 0.28 + + libEtPan! - a mail library + + * Avril Lavigne Release + + * fixed IMAP parser + * access to network protocols with a command + * pop3 driver can try APOP authentication and fallback on clear + authentication + +* 2002-12-18 - libEtPan! version 0.27 + + libEtPan! - a mail library + + * Christmas release ^^ //clindoeil + + * helper interface for IMF (RFC 2822) and MIME + * changed interface for mail threading so that a default + charset can be set. + *** this means that mail threading INTERFACE CHANGED *** + * API documentation in code + * flags directory and cache directory can be different. + *** this means that storage INTERFACE CHANGED *** + +* 2002-09-02 - libEtPan! version 0.26 + + libEtPan! - a mail library + + * flags for all cache drivers + * flags stored on disk use Berkeley DB + * mailmessage, session and storage interface are separated + *** this means that generic INTERFACE CHANGED *** + * fixes various bugs and memory leaks + + etpan - a console mail client + + * available on CVS + * virtual folder (using storage interface) is used + * folder list view / message list view / message view + * we can poll for status of mailboxes + * got rid of expat + * uses new interface of libEtPan! + +* 2002-06-26 - libEtPan! version 0.25 + + libEtPan! - a mail library + + * BSD licence + * portability tested on Solaris, FreeBSD, IRIX and Linux + * implementation of messages threads + * MIME message generator + * drivers are implemented for IMAP4rev1, POP3, NNTP, MH, mbox + in both cached and non-cached version. + + etpan - a console mail client + + * a small mail client not distributed has been implemented + written in ncurses + featuring : + - MIME message editor + - IMAP4rev1, POP3, NNTP, MH, mbox access + - renderer (HTML rendering for example) + - retrieving of MIME parts + - messages threads + + big missing feature : + - removing messages is not yet possible Added: freeswitch/trunk/libs/libetpan/Rules.in ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/Rules.in Wed Dec 20 15:28:56 2006 @@ -0,0 +1,70 @@ +# common part for sub directories Makefiles +# +# each submakefile should define SOURCES and TARGET +# optionnaly HEADRS and INCLUDES + +DESTDIR = +srcdir = $(top_builddir)/src +prefix = @prefix@ +includedir = @includedir@ +SHELL = /bin/sh +RM = rm -fr +INSTALL = @INSTALL@ +LIBTOOL = @LIBTOOL@ +CC = @CC@ +@SET_MAKE@ + +CFLAGS = -I$(top_builddir)/include -I$(top_builddir) -I. $(INCLUDES) @CFLAGS@ @CPPFLAGS@ @DEFS@ + +LDFLAGS = @LDFLAGS@ +OBJECTS = $(SOURCES:.c=.lo) + +all: $(TARGET).la + +.SUFFIXES: .lo .c + +.c.lo: + $(LIBTOOL) --mode=compile $(CC) -c $(CFLAGS) $< + +$(TARGET).la: $(OBJECTS) $(SUBLIBS) + $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(SUBLIBS) + +$(SUBLIBS) no-sublibs: all-recursive + +clean: clean-recursive + $(RM) *.o *.lo $(TARGET).la .libs *~ + +# install headers here only +install: $(HEADERS) install-recursive + for header in $(HEADERS) _listend; do \ + if [ $$header != _listend ]; then \ + $(INSTALL) -m 644 $$header $(DESTDIR)$(includedir)/libetpan ; \ + fi \ + done + +Makefile: $(top_builddir)/Rules + +$(top_builddir)/Rules: $(top_builddir)/Rules.in $(top_builddir)/config.status + cd ${top_builddir} && CONFIG_FILES=`basename $@` \ + CONFIG_HEADERS= ./config.status + +prepare: prepare-recursive + mkdir -p ${top_builddir}/include/libetpan + @for header in $(HEADERS) _listend; do \ + [ "$$header" = _listend ] && break ; \ + cmp -s "$$header" "${top_builddir}/include/libetpan/$$header" && continue ; \ + cp -pf "$$header" ${top_builddir}/include/libetpan ; \ + echo "Copied $$header -> include/libetpan/$$header" ; \ + done + +# recursive +all-recursive install-recursive clean-recursive \ + distclean-recursive prepare-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + target=`echo $@ | sed s/-recursive//`; \ + echo "Making $$target in $$subdir"; \ + (cd $$subdir && $(MAKE) $$target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" + Added: freeswitch/trunk/libs/libetpan/TODO ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/TODO Wed Dec 20 15:28:56 2006 @@ -0,0 +1,188 @@ +API documentation +----------------- + +- doc for cache + +- doc for mbox + +- doc for MH + +- doc for NNTP + +- doc for POP3 + +- comments within code + + +mail drivers +------------ + +- bodystructure should be cached + +- sort messages + +- SMTP - recipient resolver + + +IMF +--- + +- rewrite efficient RFC 2822 message parser + + +IMAP +---- + +- rewrite efficient IMAP parser + + +MIME +---- + +- generate MIME-encoded headers (done in etpan) + + +binding +------- + +- perl binding + +- objective C binding + +- C++ mapping + +- python binding + +- emacs-lisp binding + +- ocaml binding + + +miscellaneous +------------- + +- SASL authentification : cyrus-sasl + CRAM-MD5 / DIGEST-MD5 + +- S/MIME / GPG /PGP + +- filtering / scoring / searching language + +- generic tools for mail clients + +- check SSL certificates + + +compilation +----------- + +- improve autoconf / portability (header checks...) + + + +new API +------- + +wim delvaux + + +-- storage + +struct storage { + void * data; /* storage dependant */ +} + +storage_bind(&storage, driver); +storage_release(&storage); + +storage_commit(storage) + +storage_get_folder_set(storage, pattern, &set) -> list of subfolders + list of pair (basename, path) +storage_get_folder_tree(storage, pattern, &tree) -> tree of folders + tree of pair (basename, path) +folder_list_cleanup(&list) +folder_tree_cleanup(&list) + +storage_set_option(storage, option_id, value, ...) +storage_set_option_by_name(storage, option_name, value, ...) + +storage_build_folder_name(storage, name, ...) +storage_create_folder(storage, name); +storage_delete_folder(storage, name); +storage_rename_folder(storage, folder, newname); + +struct etpan_folder { + struct storage * storage; +} + +one connection per storage, +a connection can be a set of TCP/IP socket + +-- folder + +folder_bind(&folder, storage, path); +folder_release(&folder); + +folder_set_option(folder, option_id, value, ...) +folder_set_option_by_name(folder, option_name, value, ...) +folder_ctl(folder, function_id, param, ...) +folder_ctl_by_name(folder, function_name, param, ...) + +folder_get_path(folder) + +when an action is done on folder we have to query the storage state, +to see which folder we are manipulating and select the right folder. + +one binding per folder. + +several binding may be using one shared TCP/IP connection +or one TCP/IP connection for each binding. + +folder_commit(folder) -- write all flags the data down for persistant +folder_expunge(folder) -- delete messages marked as deleted +folder_status(folder, &count, &unread_count, &new_count) + -- return messages number, unread messages number, new messages number +folder_append_message(folder, message) -- add a message + (message will already contain the new flags), + really add it after commit() + +folder_get_envelopes_list(folder, &list) -- return list of message + binded to folder. +folder_fill_envelopes_list(folder, &list) -- fill the envelope info of the + list of messages. + +switch_connection_to_binding() + +struct connection { + struct current_binding * binding; +} + + +struct etpan_message { + struct etpan_folder * folder; +} + +message_bind(&message, folder, msg_id) -- initializes the message structure +message_release(&message) -- release the message +message_commit(&message) -- let the folder structure knows the flags we changed +message_get_mime_tree(&message, &mime_tree) -- return the MIME structure of + the message +message_mime_tree_cleanup(mime_tree) -- free the mime structure returned + +message_get_flags(&message, &flags) -- fetch the flags of the message +message_flags_cleanup(&message, flags) -- free the flags + +struct etpan_mime { + struct etpan_message * message; +} + +message_get_parsed_header(msg, &header) +message_get_raw_header(msg, &header) +message_get_header_set(msg, &headers) +message_get_body(msg, &Body) + +standard headers +special headers +body +flags Added: freeswitch/trunk/libs/libetpan/aclocal.m4 ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/aclocal.m4 Wed Dec 20 15:28:56 2006 @@ -0,0 +1,6382 @@ +# generated automatically by aclocal 1.9.6 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- + +# serial 48 Debian 1.5.22-4 AC_PROG_LIBTOOL + + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If this macro is not defined by Autoconf, define it here. +m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], + [m4_ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) +dnl And a similar setup for Fortran 77 support + AC_PROVIDE_IFELSE([AC_PROG_F77], + [AC_LIBTOOL_F77], + [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 +])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.50)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] + +# Same as above, but do not quote variable references. +[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AC_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +AC_DEFUN([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +]) + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +AC_DEFUN([_LT_COMPILER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +AC_DEFUN([_LT_LINKER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_LINKER_BOILERPLATE + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_SHELL_INIT(ARG) +# ---------------------- +AC_DEFUN([_LT_AC_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_AC_SHELL_INIT + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[_LT_AC_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat <<EOF +[$]* +EOF + exit 0 +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +])])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED]) +AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $rm conftest* +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# ------------------ +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# --------------------------------------------------------------------- +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<EOF +[#line __oline__ "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ---------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_ARG_WITH([tags], + [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], + [include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name \"$tagname\" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_LIBTOOL_LANG_CXX_CONFIG + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + else + tagname="" + fi + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 DLLs +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]AC_ENABLE_SHARED_DEFAULT) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +# set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]AC_ENABLE_STATIC_DEFAULT) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PROG_EGREP +# ------------- +# This is predefined starting with Autoconf 2.54, so this conditional +# definition can be removed once we require Autoconf 2.54 or later. +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], +[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], + [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognise shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognise a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AC_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break + ;; + *) + test "$with_gnu_ld" != yes && break + ;; + esac + fi + done + IFS="$lt_save_ifs" +else + lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$lt_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_PROG_LD_GNU +])# AC_PROG_LD + + +# AC_PROG_LD_GNU +# -------------- +AC_DEFUN([AC_PROG_LD_GNU], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + lt_cv_prog_gnu_ld=yes + ;; +*) + lt_cv_prog_gnu_ld=no + ;; +esac]) +with_gnu_ld=$lt_cv_prog_gnu_ld +])# AC_PROG_LD_GNU + + +# AC_PROG_LD_RELOAD_FLAG +# ---------------------- +# find reload flag for linker +# -- PORTME Some linkers may need a different reload flag. +AC_DEFUN([AC_PROG_LD_RELOAD_FLAG], +[AC_CACHE_CHECK([for $LD option to reload object files], + lt_cv_ld_reload_flag, + [lt_cv_ld_reload_flag='-r']) +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac +])# AC_PROG_LD_RELOAD_FLAG + + +# AC_DEPLIBS_CHECK_METHOD +# ----------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +AC_DEFUN([AC_DEPLIBS_CHECK_METHOD], +[AC_CACHE_CHECK([how to recognise dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix4* | aix5*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[[45]]*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump'. + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix3*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the pathname to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# it is assumed to be `libltdl'. LIBLTDL will be prefixed with +# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' +# (note the single quotes!). If your package is not flat and you're not +# using automake, define top_builddir and top_srcdir appropriately in +# the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# and an installed libltdl is not found, it is assumed to be `libltdl'. +# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and top_srcdir +# appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, lt_dlinit, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) +])# _LT_AC_LANG_CXX + +# _LT_AC_PROG_CXXCPP +# ------------------ +AC_DEFUN([_LT_AC_PROG_CXXCPP], +[ +AC_REQUIRE([AC_PROG_CXX]) +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +fi +])# _LT_AC_PROG_CXXCPP + +# AC_LIBTOOL_F77 +# -------------- +# enable support for Fortran 77 libraries +AC_DEFUN([AC_LIBTOOL_F77], +[AC_REQUIRE([_LT_AC_LANG_F77]) +])# AC_LIBTOOL_F77 + + +# _LT_AC_LANG_F77 +# --------------- +AC_DEFUN([_LT_AC_LANG_F77], +[AC_REQUIRE([AC_PROG_F77]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) +])# _LT_AC_LANG_F77 + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# ------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([LT_AC_PROG_RC]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF + +# Report which library types will actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + $as_unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + $as_unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + AC_PROG_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + ;; + *) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. We must also pass each convience library through + # to the system linker between allextract/defaultextract. + # The C++ compiler will combine linker options so we + # cannot just pass the convience library names through + # without $wl. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +AC_LIBTOOL_POSTDEP_PREDEP($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +])# AC_LIBTOOL_LANG_CXX_CONFIG + +# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) +# ------------------------------------ +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +ifelse([$1],[],[cat > conftest.$ac_ext <<EOF +int a; +void foo (void) { a = 0; } +EOF +],[$1],[CXX],[cat > conftest.$ac_ext <<EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +EOF +],[$1],[F77],[cat > conftest.$ac_ext <<EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +EOF +],[$1],[GCJ],[cat > conftest.$ac_ext <<EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +EOF +]) +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + # The `*' in the case matches for architectures that use `case' in + # $output_verbose_cmd can trigger glob expansion during the loop + # eval without this substitution. + output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"` + + for p in `eval $output_verbose_link_cmd`; do + case $p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" \ + || test $p = "-R"; then + prev=$p + continue + else + prev= + fi + + if test "$pre_test_object_deps_done" = no; then + case $p in + -L* | -R*) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + else + _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_AC_TAGVAR(postdeps, $1)"; then + _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}" + else + _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${prev}${p}" + fi + fi + ;; + + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$_LT_AC_TAGVAR(predep_objects, $1)"; then + _LT_AC_TAGVAR(predep_objects, $1)="$p" + else + _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then + _LT_AC_TAGVAR(postdep_objects, $1)="$p" + else + _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$rm -f confest.$objext + +# PORTME: override above test on systems where it is broken +ifelse([$1],[CXX], +[case $host_os in +interix3*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_AC_TAGVAR(predep_objects,$1)= + _LT_AC_TAGVAR(postdep_objects,$1)= + _LT_AC_TAGVAR(postdeps,$1)= + ;; + +solaris*) + case $cc_basename in + CC*) + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + _LT_AC_TAGVAR(postdeps,$1)='-lCstd -lCrun' + ;; + esac + ;; +esac +]) + +case " $_LT_AC_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac +])# AC_LIBTOOL_POSTDEP_PREDEP + +# AC_LIBTOOL_LANG_F77_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)]) +AC_DEFUN([_LT_AC_LANG_F77_CONFIG], +[AC_REQUIRE([AC_PROG_F77]) +AC_LANG_PUSH(Fortran 77) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code=" subroutine t\n return\n end\n" + +# Code to be used in simple link tests +lt_simple_link_test_code=" program t\n end\n" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${F77-"f77"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +_LT_AC_TAGVAR(GCC, $1)="$G77" +_LT_AC_TAGVAR(LD, $1)="$LD" + +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_F77_CONFIG + + +# AC_LIBTOOL_LANG_GCJ_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)]) +AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG], +[AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${GCJ-"gcj"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds + +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_RESTORE +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_GCJ_CONFIG + + +# AC_LIBTOOL_LANG_RC_CONFIG +# ------------------------- +# Ensure that the configuration vars for the Windows resource compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)]) +AC_DEFUN([_LT_AC_LANG_RC_CONFIG], +[AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${RC-"windres"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_RESTORE +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_RC_CONFIG + + +# AC_LIBTOOL_CONFIG([TAGNAME]) +# ---------------------------- +# If TAGNAME is not passed, then create an initial libtool script +# with a default configuration from the untagged config vars. Otherwise +# add code to config.status for appending the configuration named by +# TAGNAME from the matching tagged config vars. +AC_DEFUN([AC_LIBTOOL_CONFIG], +[# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + _LT_AC_TAGVAR(compiler, $1) \ + _LT_AC_TAGVAR(CC, $1) \ + _LT_AC_TAGVAR(LD, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \ + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \ + _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \ + _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \ + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \ + _LT_AC_TAGVAR(old_archive_cmds, $1) \ + _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \ + _LT_AC_TAGVAR(predep_objects, $1) \ + _LT_AC_TAGVAR(postdep_objects, $1) \ + _LT_AC_TAGVAR(predeps, $1) \ + _LT_AC_TAGVAR(postdeps, $1) \ + _LT_AC_TAGVAR(compiler_lib_search_path, $1) \ + _LT_AC_TAGVAR(archive_cmds, $1) \ + _LT_AC_TAGVAR(archive_expsym_cmds, $1) \ + _LT_AC_TAGVAR(postinstall_cmds, $1) \ + _LT_AC_TAGVAR(postuninstall_cmds, $1) \ + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \ + _LT_AC_TAGVAR(allow_undefined_flag, $1) \ + _LT_AC_TAGVAR(no_undefined_flag, $1) \ + _LT_AC_TAGVAR(export_symbols_cmds, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \ + _LT_AC_TAGVAR(hardcode_automatic, $1) \ + _LT_AC_TAGVAR(module_cmds, $1) \ + _LT_AC_TAGVAR(module_expsym_cmds, $1) \ + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \ + _LT_AC_TAGVAR(exclude_expsyms, $1) \ + _LT_AC_TAGVAR(include_expsyms, $1); do + + case $var in + _LT_AC_TAGVAR(old_archive_cmds, $1) | \ + _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \ + _LT_AC_TAGVAR(archive_cmds, $1) | \ + _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \ + _LT_AC_TAGVAR(module_cmds, $1) | \ + _LT_AC_TAGVAR(module_expsym_cmds, $1) | \ + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \ + _LT_AC_TAGVAR(export_symbols_cmds, $1) | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\[$]0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'` + ;; + esac + +ifelse([$1], [], + [cfgfile="${ofile}T" + trap "$rm \"$cfgfile\"; exit 1" 1 2 15 + $rm -f "$cfgfile" + AC_MSG_NOTICE([creating $ofile])], + [cfgfile="$ofile"]) + + cat <<__EOF__ >> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) +module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux* | k*bsd*-gnu) + if test "$host_cpu" = ia64; then + symcode='[[ABCDGIRSTW]]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat <<EOF > conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <<EOF >> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + linux* | k*bsd*-gnu) + _LT_AC_TAGVAR(link_all_deplibs, $1)=no + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(hardcode_automatic, $1)=no + _LT_AC_TAGVAR(module_cmds, $1)= + _LT_AC_TAGVAR(module_expsym_cmds, $1)= + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + _LT_CC_BASENAME([$compiler]) + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux* | k*bsd*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=no + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi[[45]]*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' + _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + *) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include <windows.h> +# #undef WIN32_LEAN_AND_MEAN +# #include <stdio.h> +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include <cygwin/cygwin_dll.h> +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_MSG_RESULT([$SED]) +]) + Added: freeswitch/trunk/libs/libetpan/autogen.sh ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/autogen.sh Wed Dec 20 15:28:56 2006 @@ -0,0 +1,86 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` + +# name of the current package +PKG_NAME=`basename \`(cd $srcdir; pwd)\`` + +# default configure options +conf_flags="--enable-debug --with-debug" + +DIE=0 +libtool=0 +gettext=0 +libtoolize=libtoolize + +if which glibtoolize >/dev/null 2>&1 ; then + libtoolize=glibtoolize +fi + +missing() { + echo + echo "**Error**: You must have \`$1' installed to compile $PKG_NAME." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(autoconf --version) < /dev/null > /dev/null 2>&1 || missing autoconf +(aclocal --version) < /dev/null > /dev/null 2>&1 || missing aclocal + +grep "^AM_GNU_GETTEXT" $srcdir/configure.in >/dev/null && gettext=1 +grep "^AC_PROG_LIBTOOL" $srcdir/configure.in >/dev/null && libtool=1 + +if test "$gettext" -eq 1; then + grep "sed.*POTFILES" $srcdir/configure.in >/dev/null || \ + (gettextize --version) < /dev/null > /dev/null 2>&1 || missing gettext +fi + +if test "$libtool" -eq 1; then + ($libtoolize --version) < /dev/null > /dev/null 2>&1 || missing libtool +fi + +if test "$DIE" -eq 1; then + exit 1 +fi + +if test -z "$*"; then + echo "**Warning**: I am going to run \`configure' with default arguments." + echo "If you wish to pass any others to it, please specify them on the" + echo \`$0\'" command line." + echo +else + unset conf_flags +fi + +echo "Running aclocal..." +aclocal + +if test "$gettext" -eq 1; then + echo "Running gettextize... Ignore non-fatal messages." + echo "no" | gettextize --force --copy +fi + +if test "$libtool" -eq 1; then + echo "Running libtoolize..." + $libtoolize --force --copy +fi + +echo "Running autoheader..." +autoheader +echo "Running autoconf ..." +autoconf + +if test x$NOCONFIGURE = x; then + echo Running $srcdir/configure $conf_flags "$@" ... + $srcdir/configure $conf_flags "$@" \ + && echo Now type \`make\' to compile $PKG_NAME +else + echo Skipping configure process. +fi + +if which jade >/dev/null; then + echo "Generate documentation ..." + (cd doc && make) +fi Added: freeswitch/trunk/libs/libetpan/build-windows/README.txt ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/build-windows/README.txt Wed Dec 20 15:28:56 2006 @@ -0,0 +1,50 @@ + +libEtPan! + + _________________________________________________________________ + +Windows Build: + +This folder contains the suff needed for the Windows build. + _________________________________________________________________ + +Build a version: + +1. Open libetpan.sln with VC++ 7.1 + +2. Choose configuration Debug or Release + +3. Build Solution + + This will generate libetpan.dll and readmsg.exe and the include/libetpan +folder. This folder, in combinaition with libetpan.lib, is needed for your +Windows applications using the libetpan.dll. + + _________________________________________________________________ + +Copy of headers: + +The include folder is build by build_headers.bat, the dependence is not based on headers +files themselves, but on a fake file, genarated after the .bat was executed (_headers_depends). +So, if you modify original headers (in src), you need to remove this file to refresh the +includes copy folder. + + _________________________________________________________________ + +Supported drivers: + + pop3 + imap + nntp + + _________________________________________________________________ + +TODO : + + - support mmap + - support dirent + - support Berkeley DB cache + + _________________________________________________________________ + + Added: freeswitch/trunk/libs/libetpan/build-windows/StdAfx.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/build-windows/StdAfx.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,4 @@ +#include "libetpan-config.h" + + + Added: freeswitch/trunk/libs/libetpan/build-windows/build_headers.bat ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/build-windows/build_headers.bat Wed Dec 20 15:28:56 2006 @@ -0,0 +1,4 @@ +@mkdir include +@mkdir include\libetpan +@for /F "eol=" %%i in (build_headers.list) do @copy "%%i" include\libetpan +@echo "done" >_headers_depends \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/build-windows/build_headers.list ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/build-windows/build_headers.list Wed Dec 20 15:28:56 2006 @@ -0,0 +1,157 @@ +libetpan-config.h +libetpan_version.h +..\src\data-types\base64.h +..\src\data-types\carray.h +..\src\data-types\charconv.h +..\src\data-types\chash.h +..\src\data-types\cinthash.h +..\src\data-types\clist.h +..\src\data-types\connect.h +..\src\data-types\hmac-md5.h +..\src\data-types\mail.h +..\src\data-types\maillock.h +..\src\data-types\mailsasl.h +..\src\data-types\mailsem.h +..\src\data-types\mailstream.h +..\src\data-types\mailstream_helper.h +..\src\data-types\mailstream_low.h +..\src\data-types\mailstream_socket.h +..\src\data-types\mailstream_ssl.h +..\src\data-types\mailstream_types.h +..\src\data-types\mail_cache_db.h +..\src\data-types\mail_cache_db_types.h +..\src\data-types\mapping.h +..\src\data-types\md5.h +..\src\data-types\md5global.h +..\src\data-types\mmapstring.h +..\src\driver\implementation\data-message\data_message_driver.h +..\src\driver\implementation\db\dbdriver.h +..\src\driver\implementation\db\dbdriver_message.h +..\src\driver\implementation\db\dbdriver_types.h +..\src\driver\implementation\db\dbstorage.h +..\src\driver\implementation\hotmail\hotmailstorage.h +..\src\driver\implementation\imap\imapdriver.h +..\src\driver\implementation\imap\imapdriver_cached.h +..\src\driver\implementation\imap\imapdriver_cached_message.h +..\src\driver\implementation\imap\imapdriver_message.h +..\src\driver\implementation\imap\imapdriver_tools.h +..\src\driver\implementation\imap\imapdriver_types.h +..\src\driver\implementation\imap\imapstorage.h +..\src\driver\implementation\maildir\maildirdriver.h +..\src\driver\implementation\maildir\maildirdriver_cached.h +..\src\driver\implementation\maildir\maildirdriver_cached_message.h +..\src\driver\implementation\maildir\maildirdriver_message.h +..\src\driver\implementation\maildir\maildirdriver_tools.h +..\src\driver\implementation\maildir\maildirdriver_types.h +..\src\driver\implementation\maildir\maildirstorage.h +..\src\driver\implementation\mbox\mboxdriver.h +..\src\driver\implementation\mbox\mboxdriver_cached.h +..\src\driver\implementation\mbox\mboxdriver_cached_message.h +..\src\driver\implementation\mbox\mboxdriver_message.h +..\src\driver\implementation\mbox\mboxdriver_tools.h +..\src\driver\implementation\mbox\mboxdriver_types.h +..\src\driver\implementation\mbox\mboxstorage.h +..\src\driver\implementation\mh\mhdriver.h +..\src\driver\implementation\mh\mhdriver_cached.h +..\src\driver\implementation\mh\mhdriver_cached_message.h +..\src\driver\implementation\mh\mhdriver_message.h +..\src\driver\implementation\mh\mhdriver_tools.h +..\src\driver\implementation\mh\mhdriver_types.h +..\src\driver\implementation\mh\mhstorage.h +..\src\driver\implementation\mime-message\mime_message_driver.h +..\src\driver\implementation\nntp\nntpdriver.h +..\src\driver\implementation\nntp\nntpdriver_cached.h +..\src\driver\implementation\nntp\nntpdriver_cached_message.h +..\src\driver\implementation\nntp\nntpdriver_message.h +..\src\driver\implementation\nntp\nntpdriver_tools.h +..\src\driver\implementation\nntp\nntpdriver_types.h +..\src\driver\implementation\nntp\nntpstorage.h +..\src\driver\implementation\pop3\pop3driver.h +..\src\driver\implementation\pop3\pop3driver_cached.h +..\src\driver\implementation\pop3\pop3driver_cached_message.h +..\src\driver\implementation\pop3\pop3driver_message.h +..\src\driver\implementation\pop3\pop3driver_tools.h +..\src\driver\implementation\pop3\pop3driver_types.h +..\src\driver\implementation\pop3\pop3storage.h +..\src\driver\interface\maildriver.h +..\src\driver\interface\maildriver_errors.h +..\src\driver\interface\maildriver_tools.h +..\src\driver\interface\maildriver_types.h +..\src\driver\interface\maildriver_types_helper.h +..\src\driver\interface\mailfolder.h +..\src\driver\interface\mailmessage.h +..\src\driver\interface\mailmessage_tools.h +..\src\driver\interface\mailmessage_types.h +..\src\driver\interface\mailstorage.h +..\src\driver\interface\mailstorage_tools.h +..\src\driver\interface\mailstorage_types.h +..\src\driver\tools\generic_cache.h +..\src\driver\tools\generic_cache_types.h +..\src\driver\tools\imfcache.h +..\src\driver\tools\mailthread.h +..\src\driver\tools\mailthread_types.h +..\src\engine\mailengine.h +..\src\engine\mailprivacy.h +..\src\engine\mailprivacy_gnupg.h +..\src\engine\mailprivacy_smime.h +..\src\engine\mailprivacy_tools.h +..\src\engine\mailprivacy_types.h +..\src\low-level\imap\mailimap.h +..\src\low-level\imap\mailimap_helper.h +..\src\low-level\imap\mailimap_keywords.h +..\src\low-level\imap\mailimap_parser.h +..\src\low-level\imap\mailimap_print.h +..\src\low-level\imap\mailimap_sender.h +..\src\low-level\imap\mailimap_socket.h +..\src\low-level\imap\mailimap_ssl.h +..\src\low-level\imap\mailimap_types.h +..\src\low-level\imap\mailimap_types_helper.h +..\src\low-level\imap\mailimap_extension.h +..\src\low-level\imap\mailimap_extension_types.h +..\src\low-level\imap\annotatemore.h +..\src\low-level\imap\annotatemore_parser.h +..\src\low-level\imap\annotatemore_sender.h +..\src\low-level\imap\annotatemore_types.h +..\src\low-level\imap\acl.h +..\src\low-level\imap\acl_parser.h +..\src\low-level\imap\acl_types.h +..\src\low-level\imap\acl_sender.h +..\src\low-level\imf\mailimf.h +..\src\low-level\imf\mailimf_types.h +..\src\low-level\imf\mailimf_types_helper.h +..\src\low-level\imf\mailimf_write.h +..\src\low-level\imf\mailimf_write_file.h +..\src\low-level\imf\mailimf_write_generic.h +..\src\low-level\imf\mailimf_write_mem.h +..\src\low-level\maildir\maildir.h +..\src\low-level\maildir\maildir_types.h +..\src\low-level\mbox\mailmbox.h +..\src\low-level\mbox\mailmbox_parse.h +..\src\low-level\mbox\mailmbox_types.h +..\src\low-level\mh\mailmh.h +..\src\low-level\mime\mailmime.h +..\src\low-level\mime\mailmime_content.h +..\src\low-level\mime\mailmime_decode.h +..\src\low-level\mime\mailmime_disposition.h +..\src\low-level\mime\mailmime_types.h +..\src\low-level\mime\mailmime_types_helper.h +..\src\low-level\mime\mailmime_write.h +..\src\low-level\mime\mailmime_write_file.h +..\src\low-level\mime\mailmime_write_generic.h +..\src\low-level\mime\mailmime_write_mem.h +..\src\low-level\nntp\newsnntp.h +..\src\low-level\nntp\newsnntp_socket.h +..\src\low-level\nntp\newsnntp_ssl.h +..\src\low-level\nntp\newsnntp_types.h +..\src\low-level\pop3\mailpop3.h +..\src\low-level\pop3\mailpop3_helper.h +..\src\low-level\pop3\mailpop3_socket.h +..\src\low-level\pop3\mailpop3_ssl.h +..\src\low-level\pop3\mailpop3_types.h +..\src\low-level\smtp\mailsmtp.h +..\src\low-level\smtp\mailsmtp_helper.h +..\src\low-level\smtp\mailsmtp_socket.h +..\src\low-level\smtp\mailsmtp_ssl.h +..\src\low-level\smtp\mailsmtp_types.h +..\src\main\libetpan.h +..\src\windows\win_etpan.h \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/build-windows/libetpan-config.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/build-windows/libetpan-config.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,80 @@ +#ifndef LIBETPAN_CONFIG_H +#define LIBETPAN_CONFIG_H + +#ifdef WIN32 +# define PATH_MAX 512 + +// Windows API security level +# define SECURITY_WIN32 + +# ifdef __cplusplus +# define PropVariantInit __inline PropVariantInit +# pragma warning( push ) +# pragma warning( disable : 4005 4141 ) +# endif + +# include <tchar.h> +# include <stdio.h> +# include <string.h> +# include <io.h> +# include <Winsock2.h> + +# ifdef __cplusplus +# pragma warning( pop ) +# undef PropVariantInit +# endif + +# if !defined(snprintf) +# define snprintf _snprintf +# endif +# if !defined(strncasecmp) +# define strncasecmp _strnicmp +# endif +# if !defined(strcasecmp) +# define strcasecmp _stricmp +# endif + + /* use Windows Types */ +# if !defined(ssize_t) + typedef SSIZE_T ssize_t; +# endif +# if !defined(uint16_t) + typedef UINT16 uint16_t; +# endif +# if !defined(uint32_t) + typedef UINT32 uint32_t; +# endif +# if !defined(int32_t) + typedef INT32 int32_t; +# endif +# if !defined(pid_t) + typedef DWORD pid_t; +# endif + +# if !defined(caddr_t) + typedef void * caddr_t; +# endif + + /* avoid config.h*/ +# define CONFIG_H +#endif // WIN32 + +#include <limits.h> +#ifdef _MSC_VER +# define MMAP_UNAVAILABLE +# define inline __inline +#else +# include <sys/param.h> +#endif +#define MAIL_DIR_SEPARATOR '/' +#define MAIL_DIR_SEPARATOR_S "/" +#ifdef _MSC_VER +# ifdef LIBETPAN_DLL +# define LIBETPAN_EXPORT __declspec(dllexport) +# else +# define LIBETPAN_EXPORT __declspec(dllimport) +# endif +#else +# define LIBETPAN_EXPORT +#endif +#endif Added: freeswitch/trunk/libs/libetpan/build-windows/libetpan.sln ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/build-windows/libetpan.sln Wed Dec 20 15:28:56 2006 @@ -0,0 +1,38 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libetpan", "libetpan\libetpan.vcproj", "{BA4DED3C-E56F-4484-BFC3-9C13E461A1BE}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "readmsg", "readmsg\readmsg.vcproj", "{5FEA913A-5CE4-4DEB-B6BE-B8EA1BF6F653}" + ProjectSection(ProjectDependencies) = postProject + {BA4DED3C-E56F-4484-BFC3-9C13E461A1BE} = {BA4DED3C-E56F-4484-BFC3-9C13E461A1BE} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "smtpsend", "smtpsend\smtpsend.vcproj", "{FF9F45C9-74A0-4B4E-99E9-6ADE0EB6D8AC}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {BA4DED3C-E56F-4484-BFC3-9C13E461A1BE}.Debug.ActiveCfg = Debug|Win32 + {BA4DED3C-E56F-4484-BFC3-9C13E461A1BE}.Debug.Build.0 = Debug|Win32 + {BA4DED3C-E56F-4484-BFC3-9C13E461A1BE}.Release.ActiveCfg = Release|Win32 + {BA4DED3C-E56F-4484-BFC3-9C13E461A1BE}.Release.Build.0 = Release|Win32 + {5FEA913A-5CE4-4DEB-B6BE-B8EA1BF6F653}.Debug.ActiveCfg = Debug|Win32 + {5FEA913A-5CE4-4DEB-B6BE-B8EA1BF6F653}.Debug.Build.0 = Debug|Win32 + {5FEA913A-5CE4-4DEB-B6BE-B8EA1BF6F653}.Release.ActiveCfg = Release|Win32 + {5FEA913A-5CE4-4DEB-B6BE-B8EA1BF6F653}.Release.Build.0 = Release|Win32 + {FF9F45C9-74A0-4B4E-99E9-6ADE0EB6D8AC}.Debug.ActiveCfg = Debug|Win32 + {FF9F45C9-74A0-4B4E-99E9-6ADE0EB6D8AC}.Debug.Build.0 = Debug|Win32 + {FF9F45C9-74A0-4B4E-99E9-6ADE0EB6D8AC}.Release.ActiveCfg = Release|Win32 + {FF9F45C9-74A0-4B4E-99E9-6ADE0EB6D8AC}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal Added: freeswitch/trunk/libs/libetpan/build-windows/libetpan/libetpan.vcproj ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/build-windows/libetpan/libetpan.vcproj Wed Dec 20 15:28:56 2006 @@ -0,0 +1,850 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="7.10" + Name="libetpan" + ProjectGUID="{BA4DED3C-E56F-4484-BFC3-9C13E461A1BE}" + RootNamespace="libetpan" + Keyword="Win32Proj"> + <Platforms> + <Platform + Name="Win32"/> + </Platforms> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="Debug" + IntermediateDirectory="Debug" + ConfigurationType="2" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + InlineFunctionExpansion="0" + AdditionalIncludeDirectories="../include;../include/libetpan" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBETPAN_DLL" + MinimalRebuild="TRUE" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="TRUE" + DebugInformationFormat="4" + CompileAs="1" + ForcedIncludeFiles="../StdAfx.h"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalOptions="/DLL" + AdditionalDependencies="oldnames.lib Ws2_32.lib mswsock.lib" + OutputFile="../Debug/libetpan.dll" + LinkIncremental="2" + SuppressStartupBanner="TRUE" + IgnoreDefaultLibraryNames="C" + ModuleDefinitionFile="" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile="$(OutDir)/libetpan.pdb" + MapExports="TRUE" + SubSystem="0" + ImportLibrary="../Debug/libetpan.lib" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool"/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="Release" + IntermediateDirectory="Release" + ConfigurationType="2" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="../include;../include/libetpan" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBETPAN_DLL" + RuntimeLibrary="2" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="TRUE" + DebugInformationFormat="0" + CompileAs="1" + ForcedIncludeFiles="../StdAfx.h"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalOptions="/DLL" + AdditionalDependencies="oldnames.lib Ws2_32.lib mswsock.lib" + OutputFile="../Release/libetpan.dll" + LinkIncremental="2" + IgnoreDefaultLibraryNames="C" + GenerateDebugInformation="FALSE" + SubSystem="0" + OptimizeReferences="2" + EnableCOMDATFolding="2" + ImportLibrary="../Release/libetpan.lib" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool"/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> + <File + RelativePath="..\build_headers.list"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCustomBuildTool" + CommandLine="cd .. +build_headers.bat +" + Outputs="$(InputDir)\_headers_depends"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCustomBuildTool" + CommandLine="cd .. +build_headers.bat +" + Outputs="$(InputDir)\_headers_depends"/> + </FileConfiguration> + </File> + <Filter + Name="engine" + Filter=""> + <File + RelativePath="..\..\src\engine\mailengine.c"> + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\engine\mailprivacy.c"> + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\engine\mailprivacy_gnupg.c"> + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\engine\mailprivacy_smime.c"> + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\engine\mailprivacy_tools.c"> + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + </File> + </Filter> + <Filter + Name="datatypes" + Filter=""> + <File + RelativePath="..\..\src\data-types\base64.c"> + </File> + <File + RelativePath="..\..\src\data-types\carray.c"> + </File> + <File + RelativePath="..\..\src\data-types\charconv.c"> + </File> + <File + RelativePath="..\..\src\data-types\chash.c"> + </File> + <File + RelativePath="..\..\src\data-types\cinthash.c"> + </File> + <File + RelativePath="..\..\src\data-types\clist.c"> + </File> + <File + RelativePath="..\..\src\data-types\connect.c"> + </File> + <File + RelativePath="..\..\src\data-types\mail_cache_db.c"> + </File> + <File + RelativePath="..\..\src\data-types\maillock.c"> + </File> + <File + RelativePath="..\..\src\data-types\mailsem.c"> + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\data-types\mailstream.c"> + </File> + <File + RelativePath="..\..\src\data-types\mailstream_helper.c"> + </File> + <File + RelativePath="..\..\src\data-types\mailstream_low.c"> + </File> + <File + RelativePath="..\..\src\data-types\mailstream_socket.c"> + </File> + <File + RelativePath="..\..\src\data-types\mailstream_ssl.c"> + </File> + <File + RelativePath="..\..\src\data-types\mapping.c"> + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\data-types\md5.c"> + </File> + <File + RelativePath="..\..\src\data-types\mmapstring.c"> + </File> + </Filter> + <Filter + Name="low-level" + Filter=""> + <Filter + Name="imap" + Filter=""> + <File + RelativePath="..\..\src\low-level\imap\mailimap.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\mailimap_helper.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\mailimap_keywords.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\mailimap_parser.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\mailimap_print.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\mailimap_sender.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\mailimap_socket.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\mailimap_ssl.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\mailimap_types.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\mailimap_types_helper.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\mailimap_extension.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\annotatemore.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\annotatemore_sender.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\annotatemore_types.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\annotatemore_parser.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\acl.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\acl_sender.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\acl_types.c"> + </File> + <File + RelativePath="..\..\src\low-level\imap\acl_parser.c"> + </File> + </Filter> + <Filter + Name="pop3" + Filter=""> + <File + RelativePath="..\..\src\low-level\pop3\mailpop3.c"> + </File> + <File + RelativePath="..\..\src\low-level\pop3\mailpop3_helper.c"> + </File> + <File + RelativePath="..\..\src\low-level\pop3\mailpop3_socket.c"> + </File> + <File + RelativePath="..\..\src\low-level\pop3\mailpop3_ssl.c"> + </File> + </Filter> + <Filter + Name="mime" + Filter=""> + <File + RelativePath="..\..\src\low-level\mime\mailmime.c"> + </File> + <File + RelativePath="..\..\src\low-level\mime\mailmime_content.c"> + </File> + <File + RelativePath="..\..\src\low-level\mime\mailmime_decode.c"> + </File> + <File + RelativePath="..\..\src\low-level\mime\mailmime_disposition.c"> + </File> + <File + RelativePath="..\..\src\low-level\mime\mailmime_types.c"> + </File> + <File + RelativePath="..\..\src\low-level\mime\mailmime_types_helper.c"> + </File> + <File + RelativePath="..\..\src\low-level\mime\mailmime_write.c"> + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\low-level\mime\mailmime_write_file.c"> + </File> + <File + RelativePath="..\..\src\low-level\mime\mailmime_write_generic.c"> + </File> + <File + RelativePath="..\..\src\low-level\mime\mailmime_write_mem.c"> + </File> + </Filter> + <Filter + Name="imf" + Filter=""> + <File + RelativePath="..\..\src\low-level\imf\mailimf.c"> + </File> + <File + RelativePath="..\..\src\low-level\imf\mailimf_types.c"> + </File> + <File + RelativePath="..\..\src\low-level\imf\mailimf_types_helper.c"> + </File> + <File + RelativePath="..\..\src\low-level\imf\mailimf_write.c"> + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\low-level\imf\mailimf_write_file.c"> + </File> + <File + RelativePath="..\..\src\low-level\imf\mailimf_write_generic.c"> + </File> + <File + RelativePath="..\..\src\low-level\imf\mailimf_write_mem.c"> + </File> + </Filter> + <Filter + Name="maildir" + Filter=""> + <File + RelativePath="..\..\src\low-level\maildir\maildir.c"> + </File> + </Filter> + <Filter + Name="mbox" + Filter=""> + <File + RelativePath="..\..\src\low-level\mbox\mailmbox.c"> + </File> + <File + RelativePath="..\..\src\low-level\mbox\mailmbox_parse.c"> + </File> + <File + RelativePath="..\..\src\low-level\mbox\mailmbox_types.c"> + </File> + </Filter> + <Filter + Name="mh" + Filter=""> + <File + RelativePath="..\..\src\low-level\mh\mailmh.c"> + </File> + </Filter> + <Filter + Name="nntp" + Filter=""> + <File + RelativePath="..\..\src\low-level\nntp\newsnntp.c"> + </File> + <File + RelativePath="..\..\src\low-level\nntp\newsnntp_socket.c"> + </File> + <File + RelativePath="..\..\src\low-level\nntp\newsnntp_ssl.c"> + </File> + </Filter> + <Filter + Name="smtp" + Filter=""> + <File + RelativePath="..\..\src\low-level\smtp\mailsmtp.c"> + </File> + <File + RelativePath="..\..\src\low-level\smtp\mailsmtp_helper.c"> + </File> + <File + RelativePath="..\..\src\low-level\smtp\mailsmtp_socket.c"> + </File> + <File + RelativePath="..\..\src\low-level\smtp\mailsmtp_ssl.c"> + </File> + </Filter> + </Filter> + <Filter + Name="driver" + Filter=""> + <Filter + Name="interface" + Filter=""> + <File + RelativePath="..\..\src\driver\interface\maildriver.c"> + </File> + <File + RelativePath="..\..\src\driver\interface\maildriver_tools.c"> + </File> + <File + RelativePath="..\..\src\driver\interface\maildriver_types.c"> + </File> + <File + RelativePath="..\..\src\driver\interface\maildriver_types_helper.c"> + </File> + <File + RelativePath="..\..\src\driver\interface\mailfolder.c"> + </File> + <File + RelativePath="..\..\src\driver\interface\mailmessage.c"> + </File> + <File + RelativePath="..\..\src\driver\interface\mailmessage_tools.c"> + </File> + <File + RelativePath="..\..\src\driver\interface\mailmessage_types.c"> + </File> + <File + RelativePath="..\..\src\driver\interface\mailstorage.c"> + </File> + <File + RelativePath="..\..\src\driver\interface\mailstorage_tools.c"> + </File> + </Filter> + <Filter + Name="implementation" + Filter=""> + <Filter + Name="data-message" + Filter=""> + <File + RelativePath="..\..\src\driver\implementation\data-message\data_message_driver.c"> + </File> + </Filter> + <Filter + Name="db" + Filter=""> + <File + RelativePath="..\..\src\driver\implementation\db\dbdriver.c"> + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\driver\implementation\db\dbdriver_message.c"> + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\driver\implementation\db\dbstorage.c"> + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCLCompilerTool"/> + </FileConfiguration> + </File> + </Filter> + <Filter + Name="hotmail" + Filter=""> + <File + RelativePath="..\..\src\driver\implementation\hotmail\hotmailstorage.c"> + </File> + </Filter> + <Filter + Name="imap" + Filter=""> + <File + RelativePath="..\..\src\driver\implementation\imap\imapdriver.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\imap\imapdriver_cached.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\imap\imapdriver_cached_message.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\imap\imapdriver_message.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\imap\imapdriver_tools.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\imap\imapstorage.c"> + </File> + </Filter> + <Filter + Name="maildir" + Filter=""> + <File + RelativePath="..\..\src\driver\implementation\maildir\maildirdriver.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\maildir\maildirdriver_cached.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\maildir\maildirdriver_cached_message.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\maildir\maildirdriver_message.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\maildir\maildirdriver_tools.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\maildir\maildirstorage.c"> + </File> + </Filter> + <Filter + Name="mbox" + Filter=""> + <File + RelativePath="..\..\src\driver\implementation\mbox\mboxdriver.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\mbox\mboxdriver_cached.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\mbox\mboxdriver_cached_message.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\mbox\mboxdriver_message.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\mbox\mboxdriver_tools.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\mbox\mboxstorage.c"> + </File> + </Filter> + <Filter + Name="mh" + Filter=""> + <File + RelativePath="..\..\src\driver\implementation\mh\mhdriver.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\mh\mhdriver_cached.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\mh\mhdriver_cached_message.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\mh\mhdriver_message.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\mh\mhdriver_tools.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\mh\mhstorage.c"> + </File> + </Filter> + <Filter + Name="mime-message" + Filter=""> + <File + RelativePath="..\..\src\driver\implementation\mime-message\mime_message_driver.c"> + </File> + </Filter> + <Filter + Name="nntp" + Filter=""> + <File + RelativePath="..\..\src\driver\implementation\nntp\nntpdriver.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\nntp\nntpdriver_cached.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\nntp\nntpdriver_cached_message.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\nntp\nntpdriver_message.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\nntp\nntpdriver_tools.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\nntp\nntpstorage.c"> + </File> + </Filter> + <Filter + Name="pop3" + Filter=""> + <File + RelativePath="..\..\src\driver\implementation\pop3\pop3driver.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\pop3\pop3driver_cached.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\pop3\pop3driver_cached_message.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\pop3\pop3driver_message.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\pop3\pop3driver_tools.c"> + </File> + <File + RelativePath="..\..\src\driver\implementation\pop3\pop3storage.c"> + </File> + </Filter> + </Filter> + <Filter + Name="tools" + Filter=""> + <File + RelativePath="..\..\src\driver\tools\generic_cache.c"> + </File> + <File + RelativePath="..\..\src\driver\tools\imfcache.c"> + </File> + <File + RelativePath="..\..\src\driver\tools\mailthread.c"> + </File> + <File + RelativePath="..\..\src\driver\tools\mailthread_types.c"> + </File> + </Filter> + </Filter> + <Filter + Name="Windows" + Filter=""> + <File + RelativePath="..\..\src\windows\dirent.c"> + </File> + <File + RelativePath="..\..\src\windows\misc.c"> + </File> + <File + RelativePath="..\..\src\windows\mmap.c"> + </File> + <File + RelativePath="..\..\src\windows\time_r.c"> + </File> + <File + RelativePath="..\..\src\windows\wsocket.cpp"> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + CompileAs="2"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCLCompilerTool" + CompileAs="2"/> + </FileConfiguration> + </File> + </Filter> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> + <File + RelativePath="..\libetpan-config.h"> + </File> + <File + RelativePath="..\libetpan_version.h"> + </File> + <File + RelativePath="..\StdAfx.h"> + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> Added: freeswitch/trunk/libs/libetpan/build-windows/libetpan_version.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/build-windows/libetpan_version.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,57 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: libetpan_version.h.in,v 1.3 2004/10/17 23:18:03 g_roualland Exp $ + */ + +#ifndef LIBETPAN_VERSION_H + +#define LIBETPAN_VERSION_H + +#ifndef LIBETPAN_VERSION_MAJOR +#define LIBETPAN_VERSION_MAJOR 0 +#endif + +#ifndef LIBETPAN_VERSION_MINOR +#define LIBETPAN_VERSION_MINOR 48 +#endif + +#ifndef LIBETPAN_REENTRANT +#if 1 +#define LIBETPAN_REENTRANT 1 +#endif +#endif + +int libetpan_get_version_major(void); +int libetpan_get_version_minor(void); + +#endif Added: freeswitch/trunk/libs/libetpan/build-windows/readmsg/readmsg.vcproj ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/build-windows/readmsg/readmsg.vcproj Wed Dec 20 15:28:56 2006 @@ -0,0 +1,170 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="7.10" + Name="readmsg" + ProjectGUID="{5FEA913A-5CE4-4DEB-B6BE-B8EA1BF6F653}" + Keyword="Win32Proj"> + <Platforms> + <Platform + Name="Win32"/> + </Platforms> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="Debug" + IntermediateDirectory="Debug" + ConfigurationType="1" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="../include/libetpan/;../include;../../src/gnu" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_MBCS" + MinimalRebuild="TRUE" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="TRUE" + DebugInformationFormat="4" + CompileAs="1" + ForcedIncludeFiles="../../StdAfx.h"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="libetpan.lib" + OutputFile="../Debug/readmsg.exe" + LinkIncremental="2" + AdditionalLibraryDirectories="..\Debug" + IgnoreDefaultLibraryNames="C" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile="$(OutDir)/readmsg.pdb" + SubSystem="1" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool"/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="Release" + IntermediateDirectory="Release" + ConfigurationType="1" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="../include/libetpan/;../include;../../src/gnu" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" + RuntimeLibrary="2" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="TRUE" + DebugInformationFormat="0" + ForcedIncludeFiles="../StdAfx.h"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="libetpan.lib" + OutputFile="../Release/readmsg.exe" + LinkIncremental="1" + AdditionalLibraryDirectories="..\Release" + IgnoreDefaultLibraryNames="C" + GenerateDebugInformation="TRUE" + SubSystem="1" + OptimizeReferences="2" + EnableCOMDATFolding="2" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool"/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> + <File + RelativePath="..\..\src\bsd\getopt.c"> + </File> + <File + RelativePath="..\..\src\bsd\getopt_long.c"> + </File> + <File + RelativePath="..\..\tests\Makefile"> + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCustomBuildTool"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCustomBuildTool"/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\tests\option-parser.c"> + </File> + <File + RelativePath="..\..\tests\readmsg-common.c"> + </File> + <File + RelativePath="..\..\tests\readmsg.c"> + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> Added: freeswitch/trunk/libs/libetpan/build-windows/smtpsend/smtpsend.vcproj ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/build-windows/smtpsend/smtpsend.vcproj Wed Dec 20 15:28:56 2006 @@ -0,0 +1,164 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="7.10" + Name="smtpsend" + ProjectGUID="{FF9F45C9-74A0-4B4E-99E9-6ADE0EB6D8AC}" + Keyword="Win32Proj"> + <Platforms> + <Platform + Name="Win32"/> + </Platforms> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="Debug" + IntermediateDirectory="Debug" + ConfigurationType="1" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="../include/libetpan/;../include;../../src/gnu" + PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_MBCS" + MinimalRebuild="TRUE" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="TRUE" + DebugInformationFormat="4" + CompileAs="1" + ForcedIncludeFiles="../../StdAfx.h"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="libetpan.lib" + OutputFile="../Debug/smtpsend.exe" + LinkIncremental="2" + AdditionalLibraryDirectories="..\Debug" + IgnoreDefaultLibraryNames="C" + GenerateDebugInformation="TRUE" + ProgramDatabaseFile="$(OutDir)/smtpsend.pdb" + SubSystem="1" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool"/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="Release" + IntermediateDirectory="Release" + ConfigurationType="1" + CharacterSet="2"> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="../include/libetpan/;../include;../../src/gnu" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" + RuntimeLibrary="2" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="TRUE" + DebugInformationFormat="0" + ForcedIncludeFiles="../StdAfx.h"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLinkerTool" + AdditionalDependencies="libetpan.lib" + OutputFile="../Release/smtpsend.exe" + LinkIncremental="1" + AdditionalLibraryDirectories="..\Release" + IgnoreDefaultLibraryNames="C" + GenerateDebugInformation="TRUE" + SubSystem="1" + OptimizeReferences="2" + EnableCOMDATFolding="2" + TargetMachine="1"/> + <Tool + Name="VCMIDLTool"/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCWebDeploymentTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> + <File + RelativePath="..\..\src\bsd\getopt.c"> + </File> + <File + RelativePath="..\..\src\bsd\getopt_long.c"> + </File> + <File + RelativePath="..\..\tests\Makefile"> + <FileConfiguration + Name="Debug|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCustomBuildTool"/> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + ExcludedFromBuild="TRUE"> + <Tool + Name="VCCustomBuildTool"/> + </FileConfiguration> + </File> + <File + RelativePath="..\..\tests\smtpsend.c"> + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> Added: freeswitch/trunk/libs/libetpan/config.guess ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/config.guess Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1500 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2006-07-02' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner <per@bothner.com>. +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + x86:Interix*:[3456]*) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T:Interix*:[3456]*) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <features.h> + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include <sys/param.h> +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + + http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.gues... +and + http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <config-patches@gnu.org> in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: Added: freeswitch/trunk/libs/libetpan/config.h.in ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/config.h.in Wed Dec 20 15:28:56 2006 @@ -0,0 +1,142 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Check for Linux's /usr/include/features.h + */ +#ifdef _FEATURES_H +# error config.h must be first file included +#endif + +/* Define to detected Berkeley DB major version number */ +#undef DBVERS + +/* Define to 1 if you have the <ctype.h> header file. */ +#undef HAVE_CTYPE_H + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the <fcntl.h> header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `getpagesize' function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the iconv() function. */ +#undef HAVE_ICONV + +/* prototype of iconv() has const parameters */ +#undef HAVE_ICONV_PROTO_CONST + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to enable IPv6 support. */ +#undef HAVE_IPV6 + +/* Define to 1 if you have the `lockfile' library (-llockfile). */ +#undef HAVE_LIBLOCKFILE + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define to 1 if you have the <limits.h> header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define to 1 if you have the <netdb.h> header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the <netinet/in.h> header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the <pthread.h> header file. */ +#undef HAVE_PTHREAD_H + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the <sys/mman.h> header file. */ +#undef HAVE_SYS_MMAN_H + +/* Define to 1 if you have the <sys/param.h> header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the <sys/select.h> header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the <sys/socket.h> header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define to include multithreading support */ +#undef LIBETPAN_REENTRANT + +/* Define this to the version of libEtPan */ +#undef LIBETPAN_VERSION + +/* Define this to the major version of libEtPan */ +#undef LIBETPAN_VERSION_MAJOR + +/* Define this to the minor version of libEtPan */ +#undef LIBETPAN_VERSION_MINOR + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to be lazy on protocol syntax */ +#undef UNSTRICT_SYNTAX + +/* Define to use GnuTLS */ +#undef USE_GNUTLS + +/* Define to use SASL */ +#undef USE_SASL + +/* Define to use OpenSSL */ +#undef USE_SSL + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif Added: freeswitch/trunk/libs/libetpan/config.sub ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/config.sub Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1608 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. + +timestamp='2006-07-02' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: Added: freeswitch/trunk/libs/libetpan/configure ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/configure Wed Dec 20 15:28:56 2006 @@ -0,0 +1,25425 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.60a. +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + +if test "x$CONFIG_SHELL" = x; then + if (eval ":") 2>/dev/null; then + as_have_required=yes +else + as_have_required=no +fi + + if test $as_have_required = yes && (eval ": +(as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=\$LINENO + as_lineno_2=\$LINENO + test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && + test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } +") 2> /dev/null; then + : +else + as_candidate_shells= + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /usr/bin/posix$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + case $as_dir in + /*) + for as_base in sh bash ksh sh5; do + as_candidate_shells="$as_candidate_shells $as_dir/$as_base" + done;; + esac +done +IFS=$as_save_IFS + + + for as_shell in $as_candidate_shells $SHELL; do + # Try only shells that exist, to save several forks. + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { ("$as_shell") 2> /dev/null <<\_ASEOF +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +: +_ASEOF +}; then + CONFIG_SHELL=$as_shell + as_have_required=yes + if { "$as_shell" 2> /dev/null <<\_ASEOF +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +: +(as_func_return () { + (exit $1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = "$1" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test $exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } + +_ASEOF +}; then + break +fi + +fi + + done + + if test "x$CONFIG_SHELL" != x; then + for as_var in BASH_ENV ENV + do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + done + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + + if test $as_have_required = no; then + echo This script requires a shell more modern than all the + echo shells that I found on your system. Please install a + echo modern shell, or manually run the script under such a + echo shell if you do have one. + { (exit 1); exit 1; } +fi + + +fi + +fi + + + +(eval "as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0") || { + echo No shell found that supports shell functions. + echo Please tell autoconf@gnu.org about your system, + echo including any error possibly output before this + echo message +} + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +# Find out whether ``test -x'' works. Don't use a zero-byte file, as +# systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + as_executable_p="test -x" +else + as_executable_p=: +fi +rm -f conf$$.file + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` + ;; +esac + +echo=${ECHO-echo} +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <<EOF +$* +EOF + exit 0 +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL $0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL $0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "$0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" +fi + + + + +tagnames=${tagnames+${tagnames},}CXX + +tagnames=${tagnames+${tagnames},}F77 + +exec 7<&0 </dev/null 6>&1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="src/main/libetpan_version.h.in" +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subst_vars='SHELL +PATH_SEPARATOR +PACKAGE_NAME +PACKAGE_TARNAME +PACKAGE_VERSION +PACKAGE_STRING +PACKAGE_BUGREPORT +exec_prefix +prefix +program_transform_name +bindir +sbindir +libexecdir +datarootdir +datadir +sysconfdir +sharedstatedir +localstatedir +includedir +oldincludedir +docdir +infodir +htmldir +dvidir +pdfdir +psdir +libdir +localedir +mandir +DEFS +ECHO_C +ECHO_N +ECHO_T +LIBS +build_alias +host_alias +target_alias +API_VERSION +CC +CFLAGS +LDFLAGS +CPPFLAGS +ac_ct_CC +EXEEXT +OBJEXT +build +build_cpu +build_vendor +build_os +host +host_cpu +host_vendor +host_os +GREP +EGREP +LN_S +ECHO +AR +RANLIB +STRIP +CPP +CXX +CXXFLAGS +ac_ct_CXX +CXXCPP +F77 +FFLAGS +ac_ct_F77 +LIBTOOL +SET_MAKE +INSTALL +SSLLIBS +GNUTLSLIB +LIBICONV +DBLIB +LIBSUFFIX +REENTRANT +VERSION_MAJOR +VERSION_MINOR +SASLLIBS +VERSION +LIBOBJS +LTLIBOBJS' +ac_subst_files='' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +CPPFLAGS +CPP +CXX +CXXFLAGS +CCC +CXXCPP +F77 +FFLAGS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval enable_$ac_feature=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval enable_$ac_feature=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval with_$ac_package=\$ac_optarg ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval with_$ac_package=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute directory names. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; } +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + { echo "$as_me: error: Working directory cannot be determined" >&2 + { (exit 1); exit 1; }; } +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + { echo "$as_me: error: pwd does not report name of working directory" >&2 + { (exit 1); exit 1; }; } + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$0" || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 + { (exit 1); exit 1; }; } + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-debug setup flags (gcc) for debugging (default=no) + --enable-optim setup flags (gcc) for optimizations (default=no) + --enable-unstrict-syntax be lazy on syntax checking for protocols (default=no) + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --disable-iconv make a version not using iconv + --disable-db disable Berkeley DB (default=try to detect DB) + --disable-threads do not include multithreading support using pthread + --disable-ipv6 enable IPv6 support (default=yes) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-pic try to use only PIC/non-PIC objects [default=use + both] + --with-tags[=TAGS] include additional configurations [automatic] + --with-openssl=DIR include OpenSSL support (default=auto) + --with-gnutls=DIR include GnuTLS support (default=auto) + --with-sasl=DIR include SASL support (default=auto) + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if + you have headers in a nonstandard directory <include dir> + CPP C preprocessor + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CXXCPP C++ preprocessor + F77 Fortran 77 compiler command + FFLAGS Fortran 77 compiler flags + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.60a + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.60a. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args '$ac_arg'" + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -n "$CONFIG_SITE"; then + set x "$CONFIG_SITE" +elif test "x$prefix" != xNONE; then + set x "$prefix/share/config.site" "$prefix/etc/config.site" +else + set x "$ac_default_prefix/share/config.site" \ + "$ac_default_prefix/etc/config.site" +fi +shift +for ac_site_file +do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + + + + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +VERSION_MAJOR=0 +VERSION_MINOR=48 + +API_CURRENT=10 +API_REVISION=0 +API_COMPATIBILITY=10 + +API_AGE=`expr $API_CURRENT - $API_COMPATIBILITY` +API_VERSION="$API_CURRENT:$API_REVISION:$API_AGE" + + +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then + enableval=$enable_debug; CFLAGS="$CFLAGS -O2 -g" +CPPFLAGS="$CPPFLAGS -DDEBUG" +LDFLAGS="$LDFLAGS" +fi + +# Check whether --enable-optim was given. +if test "${enable_optim+set}" = set; then + enableval=$enable_optim; if test "x$enable_debug" != "xyes" ; then + CFLAGS="$CFLAGS -O2 -ffast-math -funroll-loops -g0" + CPPFLAGS="$CPPFLAGS" + LDFLAGS="$LDFLAGS -s" +else + { echo "$as_me:$LINENO: WARNING: enable-optim and enable-debug are incompatible -- disabling optimizations" >&5 +echo "$as_me: WARNING: enable-optim and enable-debug are incompatible -- disabling optimizations" >&2;} +fi +fi + +CFLAGS="$CFLAGS -W -Wall" +# Check whether --enable-syntax was given. +if test "${enable_syntax+set}" = set; then + enableval=$enable_syntax; +else + +cat >>confdefs.h <<\_ACEOF +#define UNSTRICT_SYNTAX 1 +_ACEOF + +fi + + +ac_config_headers="$ac_config_headers config.h" + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +# +# List of possible output files, starting from the most likely. +# The algorithm is not robust to junk in `.', hence go to wildcards (a.*) +# only as a last resort. b.out is created by i960 compilers. +ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' +# +# The IRIX 6 linker writes into existing files which may not be +# executable, retaining their permissions. Remove them first so a +# subsequent execution test works. +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { (ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi + +{ echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6; } +if test -z "$ac_file"; then + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext + +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6; } + +{ echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +{ echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; + xno) + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for inline" >&5 +echo $ECHO_N "checking for inline... $ECHO_C" >&6; } +if test "${ac_cv_c_inline+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_inline=$ac_kw +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 +echo "${ECHO_T}$ac_cv_c_inline" >&6; } + + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; + xno) + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +# Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + +# Check whether --enable-static was given. +if test "${enable_static+set}" = set; then + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi + + +# Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 +echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} + { (exit 1); exit 1; }; } +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 +echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} + { (exit 1); exit 1; }; } + +{ echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6; } +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 +echo "$as_me: error: invalid value of canonical build" >&2;} + { (exit 1); exit 1; }; };; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6; } +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 +echo "$as_me: error: invalid value of canonical host" >&2;} + { (exit 1); exit 1; }; };; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 +echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6; } +if test "${lt_cv_path_SED+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done + +fi + +SED=$lt_cv_path_SED +{ echo "$as_me:$LINENO: result: $SED" >&5 +echo "${ECHO_T}$SED" >&6; } + +{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 +echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Extract the first word of "grep ggrep" to use in msg output +if test -z "$GREP"; then +set dummy grep ggrep; ac_prog_name=$2 +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_GREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_executable_p "$ac_path_GREP"; } || continue + # Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_GREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +GREP="$ac_cv_path_GREP" +if test -z "$GREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_GREP=$GREP +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 +echo "${ECHO_T}$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + # Extract the first word of "egrep" to use in msg output +if test -z "$EGREP"; then +set dummy egrep; ac_prog_name=$2 +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_EGREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_executable_p "$ac_path_EGREP"; } || continue + # Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_EGREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +EGREP="$ac_cv_path_EGREP" +if test -z "$EGREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_EGREP=$EGREP +fi + + + fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 +echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { echo "$as_me:$LINENO: checking for ld used by $CC" >&5 +echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { echo "$as_me:$LINENO: checking for GNU ld" >&5 +echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; } +else + { echo "$as_me:$LINENO: checking for non-GNU ld" >&5 +echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; } +fi +if test "${lt_cv_path_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break + ;; + *) + test "$with_gnu_ld" != yes && break + ;; + esac + fi + done + IFS="$lt_save_ifs" +else + lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$lt_cv_path_LD" +if test -n "$LD"; then + { echo "$as_me:$LINENO: result: $LD" >&5 +echo "${ECHO_T}$LD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi +test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 +echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} + { (exit 1); exit 1; }; } +{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 +echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; } +if test "${lt_cv_prog_gnu_ld+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + lt_cv_prog_gnu_ld=yes + ;; +*) + lt_cv_prog_gnu_ld=no + ;; +esac +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5 +echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + +{ echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 +echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6; } +if test "${lt_cv_ld_reload_flag+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 +echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 +echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6; } +if test "${lt_cv_path_NM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi +fi +{ echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 +echo "${ECHO_T}$lt_cv_path_NM" >&6; } +NM="$lt_cv_path_NM" + +{ echo "$as_me:$LINENO: checking whether ln -s works" >&5 +echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else + { echo "$as_me:$LINENO: result: no, using $LN_S" >&5 +echo "${ECHO_T}no, using $LN_S" >&6; } +fi + +{ echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5 +echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6; } +if test "${lt_cv_deplibs_check_method+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix4* | aix5*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump'. + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix3*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 +echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6; } +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line 4614 "configure"' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 +echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6; } +if test "${lt_cv_cc_needs_belf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + lt_cv_cc_needs_belf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + lt_cv_cc_needs_belf=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 +echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + + +esac + +need_locks="$enable_libtool_lock" + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ctype.h> +#include <stdlib.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in dlfcn.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; } +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; } +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CXXFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; } +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +fi + + +ac_ext=f +ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' +ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_f77_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in g77 f77 xlf frt pgf77 cf77 fort77 fl32 af77 f90 xlf90 pgf90 pghpf epcf90 gfortran g95 f95 fort xlf95 ifort ifc efc pgf95 lf95 ftn + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$F77"; then + ac_cv_prog_F77="$F77" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_F77="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +F77=$ac_cv_prog_F77 +if test -n "$F77"; then + { echo "$as_me:$LINENO: result: $F77" >&5 +echo "${ECHO_T}$F77" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$F77" && break + done +fi +if test -z "$F77"; then + ac_ct_F77=$F77 + for ac_prog in g77 f77 xlf frt pgf77 cf77 fort77 fl32 af77 f90 xlf90 pgf90 pghpf epcf90 gfortran g95 f95 fort xlf95 ifort ifc efc pgf95 lf95 ftn +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_F77"; then + ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_F77="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_F77=$ac_cv_prog_ac_ct_F77 +if test -n "$ac_ct_F77"; then + { echo "$as_me:$LINENO: result: $ac_ct_F77" >&5 +echo "${ECHO_T}$ac_ct_F77" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_F77" && break +done + + if test "x$ac_ct_F77" = x; then + F77="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + F77=$ac_ct_F77 + fi +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for Fortran 77 compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +rm -f a.out + +# If we don't use `.F' as extension, the preprocessor is not run on the +# input file. (Note that this only needs to work for GNU compilers.) +ac_save_ext=$ac_ext +ac_ext=F +{ echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6; } +if test "${ac_cv_f77_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF + program main +#ifndef __GNUC__ + choke me +#endif + + end +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_f77_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6; } +ac_ext=$ac_save_ext +ac_test_FFLAGS=${FFLAGS+set} +ac_save_FFLAGS=$FFLAGS +FFLAGS= +{ echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5 +echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_f77_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + FFLAGS=-g +cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_f77_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_prog_f77_g=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5 +echo "${ECHO_T}$ac_cv_prog_f77_g" >&6; } +if test "$ac_test_FFLAGS" = set; then + FFLAGS=$ac_save_FFLAGS +elif test $ac_cv_prog_f77_g = yes; then + if test "x$ac_cv_f77_compiler_gnu" = xyes; then + FFLAGS="-g -O2" + else + FFLAGS="-g" + fi +else + if test "x$ac_cv_f77_compiler_gnu" = xyes; then + FFLAGS="-O2" + else + FFLAGS= + fi +fi + +G77=`test $ac_compiler_gnu = yes && echo yes` +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! + +# find the maximum length of command line arguments +{ echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 +echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6; } +if test "${lt_cv_sys_max_cmd_len+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 +echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6; } +else + { echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6; } +fi + + + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 +echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; } +if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32*) + symcode='[ABCDGISTW]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux* | k*bsd*-gnu) + if test "$host_cpu" = ia64; then + symcode='[ABCDGIRSTW]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +EOF + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat <<EOF > conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <<EOF >> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { echo "$as_me:$LINENO: result: failed" >&5 +echo "${ECHO_T}failed" >&6; } +else + { echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6; } +fi + +{ echo "$as_me:$LINENO: checking for objdir" >&5 +echo $ECHO_N "checking for objdir... $ECHO_C" >&6; } +if test "${lt_cv_objdir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5 +echo "${ECHO_T}$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { echo "$as_me:$LINENO: result: $AR" >&5 +echo "${ECHO_T}$AR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 +echo "${ECHO_T}$ac_ct_AR" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 +echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6; } +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 +echo "${ECHO_T}$MAGIC_CMD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { echo "$as_me:$LINENO: checking for file" >&5 +echo $ECHO_N "checking for file... $ECHO_C" >&6; } +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 +echo "${ECHO_T}$MAGIC_CMD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +enable_dlopen=no +enable_win32_dll=no + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then + withval=$with_pic; pic_mode="$withval" +else + pic_mode=default +fi + +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag=' -fno-builtin' + + +{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7464: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:7468: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + +lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic='-qnocommon' + lt_prog_compiler_wl='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7732: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:7736: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6; } + +if test x"$lt_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works=yes + fi + else + lt_prog_compiler_static_works=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works" >&6; } + +if test x"$lt_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:7836: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:7840: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + runpath_var= + allow_undefined_flag= + enable_shared_with_static_runtimes=no + archive_cmds= + archive_expsym_cmds= + old_archive_From_new_cmds= + old_archive_from_expsyms_cmds= + export_dynamic_flag_spec= + whole_archive_flag_spec= + thread_safe_flag_spec= + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= + hardcode_libdir_separator= + hardcode_direct=no + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + link_all_deplibs=unknown + hardcode_automatic=no + module_cmds= + module_expsym_cmds= + always_export_symbols=no + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <<EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + + # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + ld_shlibs=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + interix3*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux* | k*bsd*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + archive_cmds='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + link_all_deplibs=no + else + ld_shlibs=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct=yes + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # see comment about different semantics on the GNU ld section + ld_shlibs=no + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + whole_archive_flag_spec='' + link_all_deplibs=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs=no + ;; + esac + fi + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + hardcode_direct=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld='+b $libdir' + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld='-rpath $libdir' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + link_all_deplibs=yes + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + openbsd*) + hardcode_direct=yes + hardcode_shlibpath_var=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; + *) + whole_archive_flag_spec='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $ld_shlibs" >&5 +echo "${ECHO_T}$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc=no + else + archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5 +echo "${ECHO_T}$archive_cmds_need_lc" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var" || \ + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action" >&5 +echo "${ECHO_T}$hardcode_action" >&6; } + +if test "$hardcode_action" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + +striplib= +old_striplib= +{ echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 +echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + ;; + *) + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + ;; + esac +fi + +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dl_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + { echo "$as_me:$LINENO: checking for shl_load" >&5 +echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; } +if test "${ac_cv_func_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define shl_load innocuous_shl_load + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shl_load (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef shl_load + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_shl_load || defined __stub___shl_load +choke me +#endif + +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 +echo "${ECHO_T}$ac_cv_func_shl_load" >&6; } +if test $ac_cv_func_shl_load = yes; then + lt_cv_dlopen="shl_load" +else + { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_shl_load=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } +if test $ac_cv_lib_dld_shl_load = yes; then + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" +else + { echo "$as_me:$LINENO: checking for dlopen" >&5 +echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; } +if test "${ac_cv_func_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define dlopen innocuous_dlopen + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char dlopen (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef dlopen + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_dlopen || defined __stub___dlopen +choke me +#endif + +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 +echo "${ECHO_T}$ac_cv_func_dlopen" >&6; } +if test $ac_cv_func_dlopen = yes; then + lt_cv_dlopen="dlopen" +else + { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dl_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; } +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 +echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; } +if test "${ac_cv_lib_svld_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_svld_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_svld_dlopen=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; } +if test $ac_cv_lib_svld_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 +echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; } +if test "${ac_cv_lib_dld_dld_link+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_dld_link=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dld_dld_link=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } +if test $ac_cv_lib_dld_dld_link = yes; then + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 +echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6; } +if test "${lt_cv_dlopen_self+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<EOF +#line 10277 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 +echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6; } +if test "${lt_cv_dlopen_self_static+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<EOF +#line 10377 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + +# Report which library types will actually be built +{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 +echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $can_build_shared" >&5 +echo "${ECHO_T}$can_build_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 +echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; } +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +{ echo "$as_me:$LINENO: result: $enable_shared" >&5 +echo "${ECHO_T}$enable_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5 +echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; } +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +{ echo "$as_me:$LINENO: result: $enable_static" >&5 +echo "${ECHO_T}$enable_static" >&6; } + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler \ + CC \ + LD \ + lt_prog_compiler_wl \ + lt_prog_compiler_pic \ + lt_prog_compiler_static \ + lt_prog_compiler_no_builtin_flag \ + export_dynamic_flag_spec \ + thread_safe_flag_spec \ + whole_archive_flag_spec \ + enable_shared_with_static_runtimes \ + old_archive_cmds \ + old_archive_from_new_cmds \ + predep_objects \ + postdep_objects \ + predeps \ + postdeps \ + compiler_lib_search_path \ + archive_cmds \ + archive_expsym_cmds \ + postinstall_cmds \ + postuninstall_cmds \ + old_archive_from_expsyms_cmds \ + allow_undefined_flag \ + no_undefined_flag \ + export_symbols_cmds \ + hardcode_libdir_flag_spec \ + hardcode_libdir_flag_spec_ld \ + hardcode_libdir_separator \ + hardcode_automatic \ + module_cmds \ + module_expsym_cmds \ + lt_cv_prog_compiler_c_o \ + exclude_expsyms \ + include_expsyms; do + + case $var in + old_archive_cmds | \ + old_archive_from_new_cmds | \ + archive_cmds | \ + archive_expsym_cmds | \ + module_cmds | \ + module_expsym_cmds | \ + old_archive_from_expsyms_cmds | \ + export_symbols_cmds | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="${ofile}T" + trap "$rm \"$cfgfile\"; exit 1" 1 2 15 + $rm -f "$cfgfile" + { echo "$as_me:$LINENO: creating $ofile" >&5 +echo "$as_me: creating $ofile" >&6;} + + cat <<__EOF__ >> "$cfgfile" +#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU C compiler? +with_gcc=$GCC + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# ### END LIBTOOL CONFIG + +__EOF__ + + + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + +# Check whether --with-tags was given. +if test "${with_tags+set}" = set; then + withval=$with_tags; tagnames="$withval" +fi + + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5 +echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;} + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5 +echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;} + else + { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5 +echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;} + fi + fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in + "") ;; + *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5 +echo "$as_me: error: invalid tag name: $tagname" >&2;} + { (exit 1); exit 1; }; } + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5 +echo "$as_me: error: tag name \"$tagname\" already exists" >&2;} + { (exit 1); exit 1; }; } + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + + +archive_cmds_need_lc_CXX=no +allow_undefined_flag_CXX= +always_export_symbols_CXX=no +archive_expsym_cmds_CXX= +export_dynamic_flag_spec_CXX= +hardcode_direct_CXX=no +hardcode_libdir_flag_spec_CXX= +hardcode_libdir_flag_spec_ld_CXX= +hardcode_libdir_separator_CXX= +hardcode_minus_L_CXX=no +hardcode_shlibpath_var_CXX=unsupported +hardcode_automatic_CXX=no +module_cmds_CXX= +module_expsym_cmds_CXX= +link_all_deplibs_CXX=unknown +old_archive_cmds_CXX=$old_archive_cmds +no_undefined_flag_CXX= +whole_archive_flag_spec_CXX= +enable_shared_with_static_runtimes_CXX=no + +# Dependencies to place before and after the object being linked: +predep_objects_CXX= +postdep_objects_CXX= +predeps_CXX= +postdeps_CXX= +compiler_lib_search_path_CXX= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +objext_CXX=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + $as_unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + $as_unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +compiler_CXX=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' +else + lt_prog_compiler_no_builtin_flag_CXX= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { echo "$as_me:$LINENO: checking for ld used by $CC" >&5 +echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { echo "$as_me:$LINENO: checking for GNU ld" >&5 +echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; } +else + { echo "$as_me:$LINENO: checking for non-GNU ld" >&5 +echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; } +fi +if test "${lt_cv_path_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break + ;; + *) + test "$with_gnu_ld" != yes && break + ;; + esac + fi + done + IFS="$lt_save_ifs" +else + lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$lt_cv_path_LD" +if test -n "$LD"; then + { echo "$as_me:$LINENO: result: $LD" >&5 +echo "${ECHO_T}$LD" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi +test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 +echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} + { (exit 1); exit 1; }; } +{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 +echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; } +if test "${lt_cv_prog_gnu_ld+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + lt_cv_prog_gnu_ld=yes + ;; +*) + lt_cv_prog_gnu_ld=no + ;; +esac +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5 +echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_CXX= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } +ld_shlibs_CXX=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_CXX='' + hardcode_direct_CXX=yes + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct_CXX=yes + else + # We have old collect2 + hardcode_direct_CXX=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_CXX=yes + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_libdir_separator_CXX= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols_CXX=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_CXX='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + + archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_CXX="-z nodefs" + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_CXX=' ${wl}-bernotok' + allow_undefined_flag_CXX=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_CXX='$convenience' + archive_cmds_need_lc_CXX=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_CXX=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_CXX=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_CXX='-L$libdir' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=no + enable_shared_with_static_runtimes_CXX=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_CXX=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + whole_archive_flag_spec_CXX='' + link_all_deplibs_CXX=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_CXX=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + freebsd[12]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + ld_shlibs_CXX=no + ;; + freebsd-elf*) + archive_cmds_need_lc_CXX=no + ;; + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + ld_shlibs_CXX=yes + ;; + gnu*) + ;; + hpux9*) + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + export_dynamic_flag_spec_CXX='${wl}-E' + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_CXX='+b $libdir' + ;; + *) + export_dynamic_flag_spec_CXX='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + ;; + *) + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + interix3*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + link_all_deplibs_CXX=yes + ;; + esac + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + ;; + linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + m88k*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + ld_shlibs_CXX=no + ;; + openbsd*) + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='${wl}-E' + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + allow_undefined_flag_CXX=' -expect_unresolved \*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + archive_cmds_need_lc_CXX=yes + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_shlibpath_var_CXX=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. We must also pass each convience library through + # to the system linker between allextract/defaultextract. + # The C++ compiler will combine linker options so we + # cannot just pass the convience library names through + # without $wl. + # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' + ;; + esac + link_all_deplibs_CXX=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + no_undefined_flag_CXX=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_CXX='${wl}-z,text' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + no_undefined_flag_CXX='${wl}-z,text' + allow_undefined_flag_CXX='${wl}-z,nodefs' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + export_dynamic_flag_spec_CXX='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; +esac +{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 +echo "${ECHO_T}$ld_shlibs_CXX" >&6; } +test "$ld_shlibs_CXX" = no && can_build_shared=no + +GCC_CXX="$GXX" +LD_CXX="$LD" + + +cat > conftest.$ac_ext <<EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +EOF + +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + # The `*' in the case matches for architectures that use `case' in + # $output_verbose_cmd can trigger glob expansion during the loop + # eval without this substitution. + output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"` + + for p in `eval $output_verbose_link_cmd`; do + case $p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" \ + || test $p = "-R"; then + prev=$p + continue + else + prev= + fi + + if test "$pre_test_object_deps_done" = no; then + case $p in + -L* | -R*) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$compiler_lib_search_path_CXX"; then + compiler_lib_search_path_CXX="${prev}${p}" + else + compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$postdeps_CXX"; then + postdeps_CXX="${prev}${p}" + else + postdeps_CXX="${postdeps_CXX} ${prev}${p}" + fi + fi + ;; + + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$predep_objects_CXX"; then + predep_objects_CXX="$p" + else + predep_objects_CXX="$predep_objects_CXX $p" + fi + else + if test -z "$postdep_objects_CXX"; then + postdep_objects_CXX="$p" + else + postdep_objects_CXX="$postdep_objects_CXX $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling CXX test program" +fi + +$rm -f confest.$objext + +# PORTME: override above test on systems where it is broken +case $host_os in +interix3*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + predep_objects_CXX= + postdep_objects_CXX= + postdeps_CXX= + ;; + +solaris*) + case $cc_basename in + CC*) + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + postdeps_CXX='-lCstd -lCrun' + ;; + esac + ;; +esac + + +case " $postdeps_CXX " in +*" -lc "*) archive_cmds_need_lc_CXX=no ;; +esac + +lt_prog_compiler_wl_CXX= +lt_prog_compiler_pic_CXX= +lt_prog_compiler_static_CXX= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_CXX='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + lt_prog_compiler_pic_CXX= + ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_CXX=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + else + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_CXX='-qnocommon' + lt_prog_compiler_wl_CXX='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + lt_prog_compiler_pic_CXX='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + lt_prog_compiler_pic_CXX='+Z' + fi + ;; + aCC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_CXX='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + lt_prog_compiler_wl_CXX='--backend -Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fpic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + lt_prog_compiler_pic_CXX='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd* | netbsdelf*-gnu) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + lt_prog_compiler_wl_CXX='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + lt_prog_compiler_pic_CXX='-pic' + ;; + cxx*) + # Digital/Compaq C++ + lt_prog_compiler_wl_CXX='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + lt_prog_compiler_pic_CXX='-pic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + lcc*) + # Lucid + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + lt_prog_compiler_pic_CXX='-KPIC' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + esac + ;; + vxworks*) + ;; + *) + lt_prog_compiler_can_build_shared_CXX=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_CXX"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_CXX=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:12745: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:12749: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works_CXX=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6; } + +if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then + case $lt_prog_compiler_pic_CXX in + "" | " "*) ;; + *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; + esac +else + lt_prog_compiler_pic_CXX= + lt_prog_compiler_can_build_shared_CXX=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_CXX= + ;; + *) + lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_CXX=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works_CXX=yes + fi + else + lt_prog_compiler_static_works_CXX=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6; } + +if test x"$lt_prog_compiler_static_works_CXX" = xyes; then + : +else + lt_prog_compiler_static_CXX= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:12849: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:12853: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + export_symbols_cmds_CXX="$ltdll_cmds" + ;; + cygwin* | mingw*) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([^ ]*\) [^ ]*/\1 DATA/;/^I /d;/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + linux* | k*bsd*-gnu) + link_all_deplibs_CXX=no + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + +{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 +echo "${ECHO_T}$ld_shlibs_CXX" >&6; } +test "$ld_shlibs_CXX" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_CXX" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_CXX=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_CXX in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_CXX + pic_flag=$lt_prog_compiler_pic_CXX + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_CXX + allow_undefined_flag_CXX= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_CXX=no + else + archive_cmds_need_lc_CXX=yes + fi + allow_undefined_flag_CXX=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action_CXX= +if test -n "$hardcode_libdir_flag_spec_CXX" || \ + test -n "$runpath_var_CXX" || \ + test "X$hardcode_automatic_CXX" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_CXX" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no && + test "$hardcode_minus_L_CXX" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_CXX=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_CXX=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_CXX=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5 +echo "${ECHO_T}$hardcode_action_CXX" >&6; } + +if test "$hardcode_action_CXX" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_CXX \ + CC_CXX \ + LD_CXX \ + lt_prog_compiler_wl_CXX \ + lt_prog_compiler_pic_CXX \ + lt_prog_compiler_static_CXX \ + lt_prog_compiler_no_builtin_flag_CXX \ + export_dynamic_flag_spec_CXX \ + thread_safe_flag_spec_CXX \ + whole_archive_flag_spec_CXX \ + enable_shared_with_static_runtimes_CXX \ + old_archive_cmds_CXX \ + old_archive_from_new_cmds_CXX \ + predep_objects_CXX \ + postdep_objects_CXX \ + predeps_CXX \ + postdeps_CXX \ + compiler_lib_search_path_CXX \ + archive_cmds_CXX \ + archive_expsym_cmds_CXX \ + postinstall_cmds_CXX \ + postuninstall_cmds_CXX \ + old_archive_from_expsyms_cmds_CXX \ + allow_undefined_flag_CXX \ + no_undefined_flag_CXX \ + export_symbols_cmds_CXX \ + hardcode_libdir_flag_spec_CXX \ + hardcode_libdir_flag_spec_ld_CXX \ + hardcode_libdir_separator_CXX \ + hardcode_automatic_CXX \ + module_cmds_CXX \ + module_expsym_cmds_CXX \ + lt_cv_prog_compiler_c_o_CXX \ + exclude_expsyms_CXX \ + include_expsyms_CXX; do + + case $var in + old_archive_cmds_CXX | \ + old_archive_from_new_cmds_CXX | \ + archive_cmds_CXX | \ + archive_expsym_cmds_CXX | \ + module_cmds_CXX | \ + module_expsym_cmds_CXX | \ + old_archive_from_expsyms_cmds_CXX | \ + export_symbols_cmds_CXX | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_CXX + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_CXX + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_CXX + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_CXX + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_CXX +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_CXX + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_CXX +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_CXX +archive_expsym_cmds=$lt_archive_expsym_cmds_CXX +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_CXX +module_expsym_cmds=$lt_module_expsym_cmds_CXX + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_CXX + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_CXX + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_CXX + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_CXX + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_CXX + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_CXX + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_CXX + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_CXX + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_CXX + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_CXX + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_CXX + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_CXX" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_CXX + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_CXX + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_CXX + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_CXX + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld + + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + +ac_ext=f +ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' +ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_f77_compiler_gnu + + +archive_cmds_need_lc_F77=no +allow_undefined_flag_F77= +always_export_symbols_F77=no +archive_expsym_cmds_F77= +export_dynamic_flag_spec_F77= +hardcode_direct_F77=no +hardcode_libdir_flag_spec_F77= +hardcode_libdir_flag_spec_ld_F77= +hardcode_libdir_separator_F77= +hardcode_minus_L_F77=no +hardcode_automatic_F77=no +module_cmds_F77= +module_expsym_cmds_F77= +link_all_deplibs_F77=unknown +old_archive_cmds_F77=$old_archive_cmds +no_undefined_flag_F77= +whole_archive_flag_spec_F77= +enable_shared_with_static_runtimes_F77=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +objext_F77=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code=" subroutine t\n return\n end\n" + +# Code to be used in simple link tests +lt_simple_link_test_code=" program t\n end\n" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${F77-"f77"} +compiler=$CC +compiler_F77=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 +echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $can_build_shared" >&5 +echo "${ECHO_T}$can_build_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 +echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; } +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +{ echo "$as_me:$LINENO: result: $enable_shared" >&5 +echo "${ECHO_T}$enable_shared" >&6; } + +{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5 +echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; } +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +{ echo "$as_me:$LINENO: result: $enable_static" >&5 +echo "${ECHO_T}$enable_static" >&6; } + +GCC_F77="$G77" +LD_F77="$LD" + +lt_prog_compiler_wl_F77= +lt_prog_compiler_pic_F77= +lt_prog_compiler_static_F77= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_static_F77='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_F77='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_F77='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_F77='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared_F77=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_F77=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_F77='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic_F77='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl_F77='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_F77='-Bstatic' + else + lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_F77='-qnocommon' + lt_prog_compiler_wl_F77='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_F77='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl_F77='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_F77='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static_F77='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl_F77='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static_F77='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-fpic' + lt_prog_compiler_static_F77='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl_F77='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static_F77='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl_F77='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static_F77='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl_F77='-Qoption ld ';; + *) + lt_prog_compiler_wl_F77='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl_F77='-Qoption ld ' + lt_prog_compiler_pic_F77='-PIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic_F77='-Kconform_pic' + lt_prog_compiler_static_F77='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_can_build_shared_F77=no + ;; + + uts4*) + lt_prog_compiler_pic_F77='-pic' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared_F77=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_F77"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_F77=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_F77" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:14410: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:14414: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works_F77=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6; } + +if test x"$lt_prog_compiler_pic_works_F77" = xyes; then + case $lt_prog_compiler_pic_F77 in + "" | " "*) ;; + *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; + esac +else + lt_prog_compiler_pic_F77= + lt_prog_compiler_can_build_shared_F77=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_F77= + ;; + *) + lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_F77=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works_F77=yes + fi + else + lt_prog_compiler_static_works_F77=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6; } + +if test x"$lt_prog_compiler_static_works_F77" = xyes; then + : +else + lt_prog_compiler_static_F77= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_F77=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:14514: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:14518: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_F77=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + runpath_var= + allow_undefined_flag_F77= + enable_shared_with_static_runtimes_F77=no + archive_cmds_F77= + archive_expsym_cmds_F77= + old_archive_From_new_cmds_F77= + old_archive_from_expsyms_cmds_F77= + export_dynamic_flag_spec_F77= + whole_archive_flag_spec_F77= + thread_safe_flag_spec_F77= + hardcode_libdir_flag_spec_F77= + hardcode_libdir_flag_spec_ld_F77= + hardcode_libdir_separator_F77= + hardcode_direct_F77=no + hardcode_minus_L_F77=no + hardcode_shlibpath_var_F77=unsupported + link_all_deplibs_F77=unknown + hardcode_automatic_F77=no + module_cmds_F77= + module_expsym_cmds_F77= + always_export_symbols_F77=no + export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms_F77= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs_F77=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_F77='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_F77= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs_F77=no + cat <<EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + + # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + ld_shlibs_F77=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_F77=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_F77=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_F77='-L$libdir' + allow_undefined_flag_F77=unsupported + always_export_symbols_F77=no + enable_shared_with_static_runtimes_F77=yes + export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_F77=no + fi + ;; + + interix3*) + hardcode_direct_F77=no + hardcode_shlibpath_var_F77=no + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + export_dynamic_flag_spec_F77='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux* | k*bsd*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + archive_cmds_F77='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + link_all_deplibs_F77=no + else + ld_shlibs_F77=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs_F77=no + cat <<EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs_F77=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + esac + + if test "$ld_shlibs_F77" = no; then + runpath_var= + hardcode_libdir_flag_spec_F77= + export_dynamic_flag_spec_F77= + whole_archive_flag_spec_F77= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag_F77=unsupported + always_export_symbols_F77=yes + archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L_F77=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct_F77=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_F77='' + hardcode_direct_F77=yes + hardcode_libdir_separator_F77=':' + link_all_deplibs_F77=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct_F77=yes + else + # We have old collect2 + hardcode_direct_F77=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_F77=yes + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_libdir_separator_F77= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols_F77=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_F77='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_F77="-z nodefs" + archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_F77=' ${wl}-bernotok' + allow_undefined_flag_F77=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_F77='$convenience' + archive_cmds_need_lc_F77=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + # see comment about different semantics on the GNU ld section + ld_shlibs_F77=no + ;; + + bsdi[45]*) + export_dynamic_flag_spec_F77=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_F77=' ' + allow_undefined_flag_F77=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds_F77='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path_F77='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes_F77=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_F77='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc_F77=no + hardcode_direct_F77=no + hardcode_automatic_F77=yes + hardcode_shlibpath_var_F77=unsupported + whole_archive_flag_spec_F77='' + link_all_deplibs_F77=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_F77=no + ;; + esac + fi + ;; + + dgux*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_shlibpath_var_F77=no + ;; + + freebsd1*) + ld_shlibs_F77=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes + hardcode_minus_L_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + hardcode_direct_F77=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + + hardcode_direct_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_F77='+b $libdir' + hardcode_direct_F77=no + hardcode_shlibpath_var_F77=no + ;; + *) + hardcode_direct_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld_F77='-rpath $libdir' + fi + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + link_all_deplibs_F77=yes + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + newsos6) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + hardcode_shlibpath_var_F77=no + ;; + + openbsd*) + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + export_dynamic_flag_spec_F77='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-R$libdir' + ;; + *) + archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + allow_undefined_flag_F77=unsupported + archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag_F77=' -expect_unresolved \*' + archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag_F77=' -expect_unresolved \*' + archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec_F77='-rpath $libdir' + fi + hardcode_libdir_separator_F77=: + ;; + + solaris*) + no_undefined_flag_F77=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_shlibpath_var_F77=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; + *) + whole_archive_flag_spec_F77='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + link_all_deplibs_F77=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_direct_F77=yes + hardcode_minus_L_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds_F77='$CC -r -o $output$reload_objs' + hardcode_direct_F77=no + ;; + motorola) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var_F77=no + ;; + + sysv4.3*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_F77=no + export_dynamic_flag_spec_F77='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_F77=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs_F77=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + no_undefined_flag_F77='${wl}-z,text' + archive_cmds_need_lc_F77=no + hardcode_shlibpath_var_F77=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_F77='${wl}-z,text' + allow_undefined_flag_F77='${wl}-z,nodefs' + archive_cmds_need_lc_F77=no + hardcode_shlibpath_var_F77=no + hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_F77=':' + link_all_deplibs_F77=yes + export_dynamic_flag_spec_F77='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_shlibpath_var_F77=no + ;; + + *) + ld_shlibs_F77=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5 +echo "${ECHO_T}$ld_shlibs_F77" >&6; } +test "$ld_shlibs_F77" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_F77" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_F77=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_F77 in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_F77 + pic_flag=$lt_prog_compiler_pic_F77 + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_F77 + allow_undefined_flag_F77= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_F77=no + else + archive_cmds_need_lc_F77=yes + fi + allow_undefined_flag_F77=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action_F77= +if test -n "$hardcode_libdir_flag_spec_F77" || \ + test -n "$runpath_var_F77" || \ + test "X$hardcode_automatic_F77" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_F77" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no && + test "$hardcode_minus_L_F77" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_F77=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_F77=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_F77=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5 +echo "${ECHO_T}$hardcode_action_F77" >&6; } + +if test "$hardcode_action_F77" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_F77 \ + CC_F77 \ + LD_F77 \ + lt_prog_compiler_wl_F77 \ + lt_prog_compiler_pic_F77 \ + lt_prog_compiler_static_F77 \ + lt_prog_compiler_no_builtin_flag_F77 \ + export_dynamic_flag_spec_F77 \ + thread_safe_flag_spec_F77 \ + whole_archive_flag_spec_F77 \ + enable_shared_with_static_runtimes_F77 \ + old_archive_cmds_F77 \ + old_archive_from_new_cmds_F77 \ + predep_objects_F77 \ + postdep_objects_F77 \ + predeps_F77 \ + postdeps_F77 \ + compiler_lib_search_path_F77 \ + archive_cmds_F77 \ + archive_expsym_cmds_F77 \ + postinstall_cmds_F77 \ + postuninstall_cmds_F77 \ + old_archive_from_expsyms_cmds_F77 \ + allow_undefined_flag_F77 \ + no_undefined_flag_F77 \ + export_symbols_cmds_F77 \ + hardcode_libdir_flag_spec_F77 \ + hardcode_libdir_flag_spec_ld_F77 \ + hardcode_libdir_separator_F77 \ + hardcode_automatic_F77 \ + module_cmds_F77 \ + module_expsym_cmds_F77 \ + lt_cv_prog_compiler_c_o_F77 \ + exclude_expsyms_F77 \ + include_expsyms_F77; do + + case $var in + old_archive_cmds_F77 | \ + old_archive_from_new_cmds_F77 | \ + archive_cmds_F77 | \ + archive_expsym_cmds_F77 | \ + module_cmds_F77 | \ + module_expsym_cmds_F77 | \ + old_archive_from_expsyms_cmds_F77 | \ + export_symbols_cmds_F77 | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_F77 + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77 + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_F77 + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_F77 + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_F77 + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_F77 + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_F77 +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_F77 + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77 + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77 + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77 + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77 + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_F77 +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77 + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77 + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_F77 +archive_expsym_cmds=$lt_archive_expsym_cmds_F77 +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_F77 +module_expsym_cmds=$lt_module_expsym_cmds_F77 + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_F77 + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_F77 + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_F77 + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_F77 + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_F77 + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_F77 + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_F77 + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_F77 + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77 + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77 + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77 + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_F77 + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_F77 + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_F77 + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_F77 + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_F77 + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_F77" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_F77 + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_F77 + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_F77 + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_F77 + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +objext_GCJ=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${GCJ-"gcj"} +compiler=$CC +compiler_GCJ=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +archive_cmds_need_lc_GCJ=no + +old_archive_cmds_GCJ=$old_archive_cmds + + +lt_prog_compiler_no_builtin_flag_GCJ= + +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin' + + +{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:16733: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:16737: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions" +else + : +fi + +fi + +lt_prog_compiler_wl_GCJ= +lt_prog_compiler_pic_GCJ= +lt_prog_compiler_static_GCJ= + +{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_static_GCJ='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_GCJ='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_GCJ='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared_GCJ=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_GCJ=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_GCJ='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic_GCJ='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl_GCJ='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_GCJ='-Bstatic' + else + lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_GCJ='-qnocommon' + lt_prog_compiler_wl_GCJ='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl_GCJ='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_GCJ='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl_GCJ='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-fpic' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl_GCJ='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl_GCJ='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl_GCJ='-Qoption ld ';; + *) + lt_prog_compiler_wl_GCJ='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl_GCJ='-Qoption ld ' + lt_prog_compiler_pic_GCJ='-PIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic_GCJ='-Kconform_pic' + lt_prog_compiler_static_GCJ='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_can_build_shared_GCJ=no + ;; + + uts4*) + lt_prog_compiler_pic_GCJ='-pic' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared_GCJ=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6; } + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_GCJ"; then + +{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_GCJ=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_GCJ" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:17001: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:17005: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_pic_works_GCJ=yes + fi + fi + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6; } + +if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then + case $lt_prog_compiler_pic_GCJ in + "" | " "*) ;; + *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; + esac +else + lt_prog_compiler_pic_GCJ= + lt_prog_compiler_can_build_shared_GCJ=no +fi + +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_GCJ= + ;; + *) + lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\" +{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_GCJ=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works_GCJ=yes + fi + else + lt_prog_compiler_static_works_GCJ=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6; } + +if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then + : +else + lt_prog_compiler_static_GCJ= +fi + + +{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } +if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_GCJ=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:17105: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:17109: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_GCJ=yes + fi + fi + chmod u+w . 2>&5 + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6; } + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; } + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6; } + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + runpath_var= + allow_undefined_flag_GCJ= + enable_shared_with_static_runtimes_GCJ=no + archive_cmds_GCJ= + archive_expsym_cmds_GCJ= + old_archive_From_new_cmds_GCJ= + old_archive_from_expsyms_cmds_GCJ= + export_dynamic_flag_spec_GCJ= + whole_archive_flag_spec_GCJ= + thread_safe_flag_spec_GCJ= + hardcode_libdir_flag_spec_GCJ= + hardcode_libdir_flag_spec_ld_GCJ= + hardcode_libdir_separator_GCJ= + hardcode_direct_GCJ=no + hardcode_minus_L_GCJ=no + hardcode_shlibpath_var_GCJ=unsupported + link_all_deplibs_GCJ=unknown + hardcode_automatic_GCJ=no + module_cmds_GCJ= + module_expsym_cmds_GCJ= + always_export_symbols_GCJ=no + export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms_GCJ= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs_GCJ=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_GCJ='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_GCJ= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs_GCJ=no + cat <<EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + + # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + ld_shlibs_GCJ=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_GCJ=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_GCJ='-L$libdir' + allow_undefined_flag_GCJ=unsupported + always_export_symbols_GCJ=no + enable_shared_with_static_runtimes_GCJ=yes + export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + interix3*) + hardcode_direct_GCJ=no + hardcode_shlibpath_var_GCJ=no + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + export_dynamic_flag_spec_GCJ='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux* | k*bsd*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + archive_cmds_GCJ='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + link_all_deplibs_GCJ=no + else + ld_shlibs_GCJ=no + fi + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs_GCJ=no + cat <<EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs_GCJ=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + esac + + if test "$ld_shlibs_GCJ" = no; then + runpath_var= + hardcode_libdir_flag_spec_GCJ= + export_dynamic_flag_spec_GCJ= + whole_archive_flag_spec_GCJ= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag_GCJ=unsupported + always_export_symbols_GCJ=yes + archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L_GCJ=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct_GCJ=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_GCJ='' + hardcode_direct_GCJ=yes + hardcode_libdir_separator_GCJ=':' + link_all_deplibs_GCJ=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct_GCJ=yes + else + # We have old collect2 + hardcode_direct_GCJ=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_GCJ=yes + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_libdir_separator_GCJ= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols_GCJ=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_GCJ='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_GCJ="-z nodefs" + archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_GCJ=' ${wl}-bernotok' + allow_undefined_flag_GCJ=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_GCJ='$convenience' + archive_cmds_need_lc_GCJ=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + # see comment about different semantics on the GNU ld section + ld_shlibs_GCJ=no + ;; + + bsdi[45]*) + export_dynamic_flag_spec_GCJ=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_GCJ=' ' + allow_undefined_flag_GCJ=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds_GCJ='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes_GCJ=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + archive_cmds_need_lc_GCJ=no + hardcode_direct_GCJ=no + hardcode_automatic_GCJ=yes + hardcode_shlibpath_var_GCJ=unsupported + whole_archive_flag_spec_GCJ='' + link_all_deplibs_GCJ=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_GCJ=no + ;; + esac + fi + ;; + + dgux*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_shlibpath_var_GCJ=no + ;; + + freebsd1*) + ld_shlibs_GCJ=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes + hardcode_minus_L_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + hardcode_direct_GCJ=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + + hardcode_direct_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' + hardcode_direct_GCJ=no + hardcode_shlibpath_var_GCJ=no + ;; + *) + hardcode_direct_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir' + fi + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + link_all_deplibs_GCJ=yes + ;; + + netbsd* | netbsdelf*-gnu) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + newsos6) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + hardcode_shlibpath_var_GCJ=no + ;; + + openbsd*) + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + export_dynamic_flag_spec_GCJ='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + ;; + *) + archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + allow_undefined_flag_GCJ=unsupported + archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag_GCJ=' -expect_unresolved \*' + archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag_GCJ=' -expect_unresolved \*' + archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec_GCJ='-rpath $libdir' + fi + hardcode_libdir_separator_GCJ=: + ;; + + solaris*) + no_undefined_flag_GCJ=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_shlibpath_var_GCJ=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; + *) + whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + link_all_deplibs_GCJ=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_direct_GCJ=yes + hardcode_minus_L_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds_GCJ='$CC -r -o $output$reload_objs' + hardcode_direct_GCJ=no + ;; + motorola) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var_GCJ=no + ;; + + sysv4.3*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_GCJ=no + export_dynamic_flag_spec_GCJ='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_GCJ=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs_GCJ=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + no_undefined_flag_GCJ='${wl}-z,text' + archive_cmds_need_lc_GCJ=no + hardcode_shlibpath_var_GCJ=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_GCJ='${wl}-z,text' + allow_undefined_flag_GCJ='${wl}-z,nodefs' + archive_cmds_need_lc_GCJ=no + hardcode_shlibpath_var_GCJ=no + hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_GCJ=':' + link_all_deplibs_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_shlibpath_var_GCJ=no + ;; + + *) + ld_shlibs_GCJ=no + ;; + esac + fi + +{ echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5 +echo "${ECHO_T}$ld_shlibs_GCJ" >&6; } +test "$ld_shlibs_GCJ" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_GCJ" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_GCJ=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_GCJ in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_GCJ + pic_flag=$lt_prog_compiler_pic_GCJ + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ + allow_undefined_flag_GCJ= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_GCJ=no + else + archive_cmds_need_lc_GCJ=yes + fi + allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6; } + ;; + esac + fi + ;; +esac + +{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; } +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } +hardcode_action_GCJ= +if test -n "$hardcode_libdir_flag_spec_GCJ" || \ + test -n "$runpath_var_GCJ" || \ + test "X$hardcode_automatic_GCJ" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_GCJ" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no && + test "$hardcode_minus_L_GCJ" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_GCJ=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_GCJ=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_GCJ=unsupported +fi +{ echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5 +echo "${ECHO_T}$hardcode_action_GCJ" >&6; } + +if test "$hardcode_action_GCJ" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_GCJ \ + CC_GCJ \ + LD_GCJ \ + lt_prog_compiler_wl_GCJ \ + lt_prog_compiler_pic_GCJ \ + lt_prog_compiler_static_GCJ \ + lt_prog_compiler_no_builtin_flag_GCJ \ + export_dynamic_flag_spec_GCJ \ + thread_safe_flag_spec_GCJ \ + whole_archive_flag_spec_GCJ \ + enable_shared_with_static_runtimes_GCJ \ + old_archive_cmds_GCJ \ + old_archive_from_new_cmds_GCJ \ + predep_objects_GCJ \ + postdep_objects_GCJ \ + predeps_GCJ \ + postdeps_GCJ \ + compiler_lib_search_path_GCJ \ + archive_cmds_GCJ \ + archive_expsym_cmds_GCJ \ + postinstall_cmds_GCJ \ + postuninstall_cmds_GCJ \ + old_archive_from_expsyms_cmds_GCJ \ + allow_undefined_flag_GCJ \ + no_undefined_flag_GCJ \ + export_symbols_cmds_GCJ \ + hardcode_libdir_flag_spec_GCJ \ + hardcode_libdir_flag_spec_ld_GCJ \ + hardcode_libdir_separator_GCJ \ + hardcode_automatic_GCJ \ + module_cmds_GCJ \ + module_expsym_cmds_GCJ \ + lt_cv_prog_compiler_c_o_GCJ \ + exclude_expsyms_GCJ \ + include_expsyms_GCJ; do + + case $var in + old_archive_cmds_GCJ | \ + old_archive_from_new_cmds_GCJ | \ + archive_cmds_GCJ | \ + archive_expsym_cmds_GCJ | \ + module_cmds_GCJ | \ + module_expsym_cmds_GCJ | \ + old_archive_from_expsyms_cmds_GCJ | \ + export_symbols_cmds_GCJ | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_GCJ + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_GCJ + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_GCJ + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_GCJ + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_GCJ + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_GCJ +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_GCJ + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_GCJ +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_GCJ +archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_GCJ +module_expsym_cmds=$lt_module_expsym_cmds_GCJ + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_GCJ + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_GCJ + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_GCJ + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_GCJ + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_GCJ + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_GCJ + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_GCJ + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_GCJ + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_GCJ + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_GCJ + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_GCJ + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_GCJ" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_GCJ + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_GCJ + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_GCJ + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_GCJ + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + else + tagname="" + fi + ;; + + RC) + + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +objext_RC=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${RC-"windres"} +compiler=$CC +compiler_RC=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + +lt_cv_prog_compiler_c_o_RC=yes + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ + SED SHELL STRIP \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_RC \ + CC_RC \ + LD_RC \ + lt_prog_compiler_wl_RC \ + lt_prog_compiler_pic_RC \ + lt_prog_compiler_static_RC \ + lt_prog_compiler_no_builtin_flag_RC \ + export_dynamic_flag_spec_RC \ + thread_safe_flag_spec_RC \ + whole_archive_flag_spec_RC \ + enable_shared_with_static_runtimes_RC \ + old_archive_cmds_RC \ + old_archive_from_new_cmds_RC \ + predep_objects_RC \ + postdep_objects_RC \ + predeps_RC \ + postdeps_RC \ + compiler_lib_search_path_RC \ + archive_cmds_RC \ + archive_expsym_cmds_RC \ + postinstall_cmds_RC \ + postuninstall_cmds_RC \ + old_archive_from_expsyms_cmds_RC \ + allow_undefined_flag_RC \ + no_undefined_flag_RC \ + export_symbols_cmds_RC \ + hardcode_libdir_flag_spec_RC \ + hardcode_libdir_flag_spec_ld_RC \ + hardcode_libdir_separator_RC \ + hardcode_automatic_RC \ + module_cmds_RC \ + module_expsym_cmds_RC \ + lt_cv_prog_compiler_c_o_RC \ + exclude_expsyms_RC \ + include_expsyms_RC; do + + case $var in + old_archive_cmds_RC | \ + old_archive_from_new_cmds_RC | \ + archive_cmds_RC | \ + archive_expsym_cmds_RC | \ + module_cmds_RC | \ + module_expsym_cmds_RC | \ + old_archive_from_expsyms_cmds_RC | \ + export_symbols_cmds_RC | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_RC + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_compiler_RC + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_RC + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_RC + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_RC + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_RC +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_RC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_RC +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_RC +archive_expsym_cmds=$lt_archive_expsym_cmds_RC +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_RC +module_expsym_cmds=$lt_module_expsym_cmds_RC + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_RC + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_RC + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_RC + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_RC + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_RC + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_RC + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_RC + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_RC + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_RC + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_RC + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_RC + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_RC + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_RC + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_RC" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_RC + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_RC + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_RC + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_RC + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + ;; + + *) + { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5 +echo "$as_me: error: Unsupported tag name: $tagname" >&2;} + { (exit 1); exit 1; }; } + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5 +echo "$as_me: error: unable to update list of available tagged configurations." >&2;} + { (exit 1); exit 1; }; } + fi +fi + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + +# Prevent multiple expansion + + + + + + + + + + + + + + + + + + + + +{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; } +set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + SET_MAKE= +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + + +INSTALL='$(SHELL) $(top_builddir)/install-sh -c' + + +{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ctype.h> +#include <stdlib.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + + + + + + + + +for ac_header in fcntl.h unistd.h ctype.h sys/types.h sys/stat.h sys/mman.h limits.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + +for ac_header in netdb.h netinet/in.h sys/socket.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + +for ac_header in sys/param.h sys/select.h inttypes.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + +for ac_header in stdlib.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_func in getpagesize +do +as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +{ echo "$as_me:$LINENO: checking for working mmap" >&5 +echo $ECHO_N "checking for working mmap... $ECHO_C" >&6; } +if test "${ac_cv_func_mmap_fixed_mapped+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +/* malloc might have been renamed as rpl_malloc. */ +#undef malloc + +/* Thanks to Mike Haertel and Jim Avera for this test. + Here is a matrix of mmap possibilities: + mmap private not fixed + mmap private fixed at somewhere currently unmapped + mmap private fixed at somewhere already mapped + mmap shared not fixed + mmap shared fixed at somewhere currently unmapped + mmap shared fixed at somewhere already mapped + For private mappings, we should verify that changes cannot be read() + back from the file, nor mmap's back from the file at a different + address. (There have been systems where private was not correctly + implemented like the infamous i386 svr4.0, and systems where the + VM page cache was not coherent with the file system buffer cache + like early versions of FreeBSD and possibly contemporary NetBSD.) + For shared mappings, we should conversely verify that changes get + propagated back to all the places they're supposed to be. + + Grep wants private fixed already mapped. + The main things grep needs to know about mmap are: + * does it exist and is it safe to write into the mmap'd area + * how to use it (BSD variants) */ + +#include <fcntl.h> +#include <sys/mman.h> + +#if !defined STDC_HEADERS && !defined HAVE_STDLIB_H +char *malloc (); +#endif + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +int +main () +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize (); + + /* First, make a file with some known garbage in it. */ + data = (char *) malloc (pagesize); + if (!data) + return 1; + for (i = 0; i < pagesize; ++i) + *(data + i) = rand (); + umask (0); + fd = creat ("conftest.mmap", 0600); + if (fd < 0) + return 1; + if (write (fd, data, pagesize) != pagesize) + return 1; + close (fd); + + /* Next, try to mmap the file at a fixed address which already has + something else allocated at it. If we can, also make sure that + we see the same garbage. */ + fd = open ("conftest.mmap", O_RDWR); + if (fd < 0) + return 1; + data2 = (char *) malloc (2 * pagesize); + if (!data2) + return 1; + data2 += (pagesize - ((long int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + return 1; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + return 1; + + /* Finally, make sure that changes to the mapped area do not + percolate back to the file as seen by read(). (This is a bug on + some variants of i386 svr4.0.) */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = (char *) malloc (pagesize); + if (!data3) + return 1; + if (read (fd, data3, pagesize) != pagesize) + return 1; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + return 1; + close (fd); + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_func_mmap_fixed_mapped=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_mmap_fixed_mapped" >&5 +echo "${ECHO_T}$ac_cv_func_mmap_fixed_mapped" >&6; } +if test $ac_cv_func_mmap_fixed_mapped = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_MMAP 1 +_ACEOF + +fi +rm -f conftest.mmap + + +{ echo "$as_me:$LINENO: checking for connect" >&5 +echo $ECHO_N "checking for connect... $ECHO_C" >&6; } +if test "${ac_cv_func_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define connect to an innocuous variant, in case <limits.h> declares connect. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define connect innocuous_connect + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char connect (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef connect + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char connect (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_connect || defined __stub___connect +choke me +#endif + +int +main () +{ +return connect (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_connect=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 +echo "${ECHO_T}$ac_cv_func_connect" >&6; } +if test $ac_cv_func_connect = yes; then + checksocket=no +else + checksocket=yes +fi + +if test "x$checksocket" = "xyes"; then +case "x$LIBS" in + *-lsocket*);; + *) +{ echo "$as_me:$LINENO: checking for connect in -lsocket" >&5 +echo $ECHO_N "checking for connect in -lsocket... $ECHO_C" >&6; } +if test "${ac_cv_lib_socket_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char connect (); +int +main () +{ +return connect (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_socket_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_socket_connect=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_socket_connect" >&5 +echo "${ECHO_T}$ac_cv_lib_socket_connect" >&6; } +if test $ac_cv_lib_socket_connect = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSOCKET 1 +_ACEOF + + LIBS="-lsocket $LIBS" + +fi + ;; +esac +fi +{ echo "$as_me:$LINENO: checking for inet_ntoa" >&5 +echo $ECHO_N "checking for inet_ntoa... $ECHO_C" >&6; } +if test "${ac_cv_func_inet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define inet_ntoa to an innocuous variant, in case <limits.h> declares inet_ntoa. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define inet_ntoa innocuous_inet_ntoa + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char inet_ntoa (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef inet_ntoa + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char inet_ntoa (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_inet_ntoa || defined __stub___inet_ntoa +choke me +#endif + +int +main () +{ +return inet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_inet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_inet_ntoa=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_inet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_func_inet_ntoa" >&6; } +if test $ac_cv_func_inet_ntoa = yes; then + checknsl=no +else + checknsl=yes +fi + +if test "x$checknsl" = "xyes"; then +case "x$LIBS" in + *-lnsl*);; + *) +{ echo "$as_me:$LINENO: checking for inet_ntoa in -lnsl" >&5 +echo $ECHO_N "checking for inet_ntoa in -lnsl... $ECHO_C" >&6; } +if test "${ac_cv_lib_nsl_inet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char inet_ntoa (); +int +main () +{ +return inet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_nsl_inet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_nsl_inet_ntoa=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_inet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_lib_nsl_inet_ntoa" >&6; } +if test $ac_cv_lib_nsl_inet_ntoa = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNSL 1 +_ACEOF + + LIBS="-lnsl $LIBS" + +fi + ;; +esac +fi + + +# Check whether --with-openssl was given. +if test "${with_openssl+set}" = set; then + withval=$with_openssl; +else + with_openssl=yes +fi + +if test "x$with_openssl" != "xno"; then + OCPPFLAGS="$CPPFLAGS" + OLDFLAGS="$LDFLAGS" + if test "x$with_openssl" != "xyes" ; then + CPPFLAGS="$CPPFLAGS -I$with_openssl/include" + LDFLAGS="$LDFLAGS -L$with_openssl/lib" + fi + with_openssl=no + SSLLIBS="" + if test "${ac_cv_header_openssl_ssl_h+set}" = set; then + { echo "$as_me:$LINENO: checking for openssl/ssl.h" >&5 +echo $ECHO_N "checking for openssl/ssl.h... $ECHO_C" >&6; } +if test "${ac_cv_header_openssl_ssl_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_openssl_ssl_h" >&5 +echo "${ECHO_T}$ac_cv_header_openssl_ssl_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking openssl/ssl.h usability" >&5 +echo $ECHO_N "checking openssl/ssl.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <openssl/ssl.h> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking openssl/ssl.h presence" >&5 +echo $ECHO_N "checking openssl/ssl.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <openssl/ssl.h> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: openssl/ssl.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: openssl/ssl.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/ssl.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: openssl/ssl.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: openssl/ssl.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: openssl/ssl.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/ssl.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: openssl/ssl.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/ssl.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: openssl/ssl.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/ssl.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: openssl/ssl.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/ssl.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: openssl/ssl.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: openssl/ssl.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: openssl/ssl.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for openssl/ssl.h" >&5 +echo $ECHO_N "checking for openssl/ssl.h... $ECHO_C" >&6; } +if test "${ac_cv_header_openssl_ssl_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_openssl_ssl_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_openssl_ssl_h" >&5 +echo "${ECHO_T}$ac_cv_header_openssl_ssl_h" >&6; } + +fi +if test $ac_cv_header_openssl_ssl_h = yes; then + + { echo "$as_me:$LINENO: checking for main in -lrsaref" >&5 +echo $ECHO_N "checking for main in -lrsaref... $ECHO_C" >&6; } +if test "${ac_cv_lib_rsaref_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrsaref $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_rsaref_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_rsaref_main=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_rsaref_main" >&5 +echo "${ECHO_T}$ac_cv_lib_rsaref_main" >&6; } +if test $ac_cv_lib_rsaref_main = yes; then + SSLLIBS="-lrsaref" +fi + + { echo "$as_me:$LINENO: checking for main in -lcrypto" >&5 +echo $ECHO_N "checking for main in -lcrypto... $ECHO_C" >&6; } +if test "${ac_cv_lib_crypto_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $SSLLIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_crypto_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_crypto_main=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_crypto_main" >&5 +echo "${ECHO_T}$ac_cv_lib_crypto_main" >&6; } +if test $ac_cv_lib_crypto_main = yes; then + SSLLIBS="-lcrypto $SSLLIBS" +fi + + { echo "$as_me:$LINENO: checking for SSL_library_init in -lssl" >&5 +echo $ECHO_N "checking for SSL_library_init in -lssl... $ECHO_C" >&6; } +if test "${ac_cv_lib_ssl_SSL_library_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lssl $SSLLIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char SSL_library_init (); +int +main () +{ +return SSL_library_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_ssl_SSL_library_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_ssl_SSL_library_init=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_ssl_SSL_library_init" >&5 +echo "${ECHO_T}$ac_cv_lib_ssl_SSL_library_init" >&6; } +if test $ac_cv_lib_ssl_SSL_library_init = yes; then + with_openssl=yes +fi + +fi + + + if test "x$with_openssl" != "xyes"; then + CPPFLAGS="$OCPPFLAGS" + LDFLAGS="$OLDFLAGS" + else + with_gnutls="no" + fi +fi +if test "x$with_openssl" = "xyes"; then + +cat >>confdefs.h <<\_ACEOF +#define USE_SSL 1 +_ACEOF + + SSLLIBS="-lssl $SSLLIBS" +else + SSLLIBS="" +fi + + + +# Check whether --with-gnutls was given. +if test "${with_gnutls+set}" = set; then + withval=$with_gnutls; +else + with_gnutls=no +fi + +if test "x$with_gnutls" != "xno"; then + OCPPFLAGS="$CPPFLAGS" + OLDFLAGS="$LDFLAGS" + if test "x$with_gnutls" != "xyes" ; then + CPPFLAGS="CRPPFLAGS -I$with_gnutls/include" + LDFLAGS="$LDFLAGS -L$with_gnutls/lib" + fi + GNUTLSLIB="" + if test "${ac_cv_header_gnutls_gnutls_h+set}" = set; then + { echo "$as_me:$LINENO: checking for gnutls/gnutls.h" >&5 +echo $ECHO_N "checking for gnutls/gnutls.h... $ECHO_C" >&6; } +if test "${ac_cv_header_gnutls_gnutls_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_gnutls_gnutls_h" >&5 +echo "${ECHO_T}$ac_cv_header_gnutls_gnutls_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking gnutls/gnutls.h usability" >&5 +echo $ECHO_N "checking gnutls/gnutls.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <gnutls/gnutls.h> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking gnutls/gnutls.h presence" >&5 +echo $ECHO_N "checking gnutls/gnutls.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <gnutls/gnutls.h> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: gnutls/gnutls.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: gnutls/gnutls.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: gnutls/gnutls.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: gnutls/gnutls.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: gnutls/gnutls.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: gnutls/gnutls.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: gnutls/gnutls.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: gnutls/gnutls.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: gnutls/gnutls.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: gnutls/gnutls.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: gnutls/gnutls.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: gnutls/gnutls.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: gnutls/gnutls.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: gnutls/gnutls.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: gnutls/gnutls.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: gnutls/gnutls.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for gnutls/gnutls.h" >&5 +echo $ECHO_N "checking for gnutls/gnutls.h... $ECHO_C" >&6; } +if test "${ac_cv_header_gnutls_gnutls_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_gnutls_gnutls_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_gnutls_gnutls_h" >&5 +echo "${ECHO_T}$ac_cv_header_gnutls_gnutls_h" >&6; } + +fi +if test $ac_cv_header_gnutls_gnutls_h = yes; then + + { echo "$as_me:$LINENO: checking for gnutls_global_deinit in -lgnutls" >&5 +echo $ECHO_N "checking for gnutls_global_deinit in -lgnutls... $ECHO_C" >&6; } +if test "${ac_cv_lib_gnutls_gnutls_global_deinit+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgnutls $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gnutls_global_deinit (); +int +main () +{ +return gnutls_global_deinit (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_gnutls_gnutls_global_deinit=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_gnutls_gnutls_global_deinit=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_gnutls_gnutls_global_deinit" >&5 +echo "${ECHO_T}$ac_cv_lib_gnutls_gnutls_global_deinit" >&6; } +if test $ac_cv_lib_gnutls_gnutls_global_deinit = yes; then + with_gnutls=yes +else + GNUTLSLIB="-lgnutls" +fi + + +fi + + + if test "x$with_gnutls" != "xyes"; then + CPPFLAGS="$OCPPFLAGS" + LDFLAGS="$OLDFLAGS" + else + with_openssl="no" + fi +fi +if test "x$with_gnutls" = "xyes"; then + +cat >>confdefs.h <<\_ACEOF +#define USE_GNUTLS 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define USE_SSL 1 +_ACEOF + + GNUTLSLIB="-lgnutls" +else + GNUTLSLIB="" +fi + + +if test "x$with_openssl" = "xno"; then + if test "x$with_gnutls" = "xno"; then + { echo "$as_me:$LINENO: WARNING: OpenSSL support disabled." >&5 +echo "$as_me: WARNING: OpenSSL support disabled." >&2;} + fi +fi + +LIBICONV="" + +# Check whether --enable-iconv was given. +if test "${enable_iconv+set}" = set; then + enableval=$enable_iconv; enable_iconv=no +else + enable_iconv=yes +fi + +if test x$enable_iconv = xyes; then + if test "${ac_cv_header_iconv_h+set}" = set; then + { echo "$as_me:$LINENO: checking for iconv.h" >&5 +echo $ECHO_N "checking for iconv.h... $ECHO_C" >&6; } +if test "${ac_cv_header_iconv_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_iconv_h" >&5 +echo "${ECHO_T}$ac_cv_header_iconv_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking iconv.h usability" >&5 +echo $ECHO_N "checking iconv.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <iconv.h> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking iconv.h presence" >&5 +echo $ECHO_N "checking iconv.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <iconv.h> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: iconv.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: iconv.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: iconv.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: iconv.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: iconv.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: iconv.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: iconv.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: iconv.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: iconv.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: iconv.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: iconv.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: iconv.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: iconv.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: iconv.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: iconv.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: iconv.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for iconv.h" >&5 +echo $ECHO_N "checking for iconv.h... $ECHO_C" >&6; } +if test "${ac_cv_header_iconv_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_iconv_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_iconv_h" >&5 +echo "${ECHO_T}$ac_cv_header_iconv_h" >&6; } + +fi +if test $ac_cv_header_iconv_h = yes; then + ICONV_HEADER=1 +else + ICONV_HEADER=0 +fi + + + + ICONV_PROTO=no + { echo "$as_me:$LINENO: checking checking iconv() prototype" >&5 +echo $ECHO_N "checking checking iconv() prototype... $ECHO_C" >&6; } + if test "x$ICONV_HEADER" = x1 ; then + SAVED_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="-std=c99 $CPPFLAGS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <iconv.h> + size_t iconv (iconv_t cd, char ** restrict inbuf, + size_t * restrict inbytesleft, + char ** restrict outbuf, + size_t * restrict outbytesleft); +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ICONV_PROTO=noconst + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <iconv.h> + size_t iconv (iconv_t cd, const char ** restrict inbuf, + size_t * restrict inbytesleft, + char ** restrict outbuf, + size_t * restrict outbytesleft); +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ICONV_PROTO=const + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CPPFLAGS="$SAVED_CPPFLAGS" + fi + + ICONV_LINKED=NO + if test "$ICONV_PROTO" != "xno" ; then + { echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6; } + + { echo "$as_me:$LINENO: checking for iconv" >&5 +echo $ECHO_N "checking for iconv... $ECHO_C" >&6; } + + ICONV_LINKED=0 + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +#include <iconv.h> +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ICONV_LINKED=1 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + for lib in iconv ; do + if test "x$ICONV_LINKED" = "x0" ; then + LIBS=-l$lib + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +#include <iconv.h> +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + LIBICONV="$LIBS" ; ICONV_LINKED=1 +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + fi + done + LIBS="" + + if test "x$ICONV_LINKED" = "x1" ; then + { echo "$as_me:$LINENO: result: found" >&5 +echo "${ECHO_T}found" >&6; } + else + { echo "$as_me:$LINENO: result: not found" >&5 +echo "${ECHO_T}not found" >&6; } + fi + else + { echo "$as_me:$LINENO: result: failed" >&5 +echo "${ECHO_T}failed" >&6; } + fi + + if test "x$ICONV_LINKED" = "x1" ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ICONV 1 +_ACEOF + + fi + + ICONV_PROTO_CONST=0 + if test "x$ICONV_PROTO" = "xconst" ; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_ICONV_PROTO_CONST 1 +_ACEOF + + fi +fi + + + +DBVERS=0 +DBLINKED=0 +DBLIB="" + +# Check whether --enable-db was given. +if test "${enable_db+set}" = set; then + enableval=$enable_db; enable_db=$enableval +else + enable_db=yes +fi + + +if test "x$enable_db" != "xyes"; then + { echo "$as_me:$LINENO: WARNING: cache support disabled" >&5 +echo "$as_me: WARNING: cache support disabled" >&2;} +else + if test "${ac_cv_header_db_h+set}" = set; then + { echo "$as_me:$LINENO: checking for db.h" >&5 +echo $ECHO_N "checking for db.h... $ECHO_C" >&6; } +if test "${ac_cv_header_db_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_db_h" >&5 +echo "${ECHO_T}$ac_cv_header_db_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking db.h usability" >&5 +echo $ECHO_N "checking db.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <db.h> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking db.h presence" >&5 +echo $ECHO_N "checking db.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <db.h> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: db.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: db.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: db.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: db.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: db.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: db.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: db.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: db.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: db.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: db.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: db.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: db.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: db.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: db.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: db.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: db.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for db.h" >&5 +echo $ECHO_N "checking for db.h... $ECHO_C" >&6; } +if test "${ac_cv_header_db_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_db_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_db_h" >&5 +echo "${ECHO_T}$ac_cv_header_db_h" >&6; } + +fi +if test $ac_cv_header_db_h = yes; then + DB_HEADER=1 +else + DB_HEADER=0 +fi + + +fi + +if test "x$DB_HEADER" = "x1"; then + { echo "$as_me:$LINENO: checking version of Berkeley DB" >&5 +echo $ECHO_N "checking version of Berkeley DB... $ECHO_C" >&6; } + + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <db.h> +int +main () +{ +#if DB_VERSION_MAJOR < 3 + #error DB version 3 or above needed + #endif + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + DBVERS=3 + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + if test "x$DBVERS" = "x0"; then + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <db.h> +int +main () +{ +#if DB_VERSION_MAJOR != 2 + #error DB version 2 needed + #endif + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + DBVERS=2 + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + + if test "x$DBVERS" = "x0"; then + DBVERS=1 + fi + + + case "$DBVERS" in + 3) + { echo "$as_me:$LINENO: result: version 3.x or above" >&5 +echo "${ECHO_T}version 3.x or above" >&6; } + for lib in db-4.4 db-4.3 db-4.2 db-4.1 db-4.0 db-4 db4 db-3.2 db-3 db3 db; do + if test "x$DBLINKED" = "x0"; then + { echo "$as_me:$LINENO: checking for db_create() in -l$lib" >&5 +echo $ECHO_N "checking for db_create() in -l$lib... $ECHO_C" >&6; } + LIBS=-l$lib + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <db.h> +int +main () +{ +db_create(0,0,0) + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + DBLIB="-l$lib"; DBLINKED=1; { echo "$as_me:$LINENO: result: found" >&5 +echo "${ECHO_T}found" >&6; } +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: result: not found" >&5 +echo "${ECHO_T}not found" >&6; } +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + fi + done + LIBS="" + ;; + + 2) + { echo "$as_me:$LINENO: result: version 2.x" >&5 +echo "${ECHO_T}version 2.x" >&6; } + for lib in db2 db; do + if test "x$DBLINKED" = "x0"; then + as_ac_Lib=`echo "ac_cv_lib_$lib''_db_open" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for db_open in -l$lib" >&5 +echo $ECHO_N "checking for db_open in -l$lib... $ECHO_C" >&6; } +if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$lib $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char db_open (); +int +main () +{ +return db_open (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Lib=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Lib=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +ac_res=`eval echo '${'$as_ac_Lib'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Lib'}'` = yes; then + DBLIB="-l$lib"; DBLINKED=1 +fi + + fi + done + ;; + + *) + { echo "$as_me:$LINENO: result: version 1.x" >&5 +echo "${ECHO_T}version 1.x" >&6; } + { echo "$as_me:$LINENO: checking for dbopen" >&5 +echo $ECHO_N "checking for dbopen... $ECHO_C" >&6; } +if test "${ac_cv_func_dbopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define dbopen to an innocuous variant, in case <limits.h> declares dbopen. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define dbopen innocuous_dbopen + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char dbopen (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef dbopen + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dbopen (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_dbopen || defined __stub___dbopen +choke me +#endif + +int +main () +{ +return dbopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_dbopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_dbopen=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_dbopen" >&5 +echo "${ECHO_T}$ac_cv_func_dbopen" >&6; } +if test $ac_cv_func_dbopen = yes; then + DBLINKED=1 +fi + + for lib in db-1 db1 db; do + if test "x$DBLINKED" = "x0"; then + as_ac_Lib=`echo "ac_cv_lib_$lib''_dbopen" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for dbopen in -l$lib" >&5 +echo $ECHO_N "checking for dbopen in -l$lib... $ECHO_C" >&6; } +if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$lib $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dbopen (); +int +main () +{ +return dbopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Lib=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Lib=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +ac_res=`eval echo '${'$as_ac_Lib'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Lib'}'` = yes; then + DBLIB="-l$lib"; DBLINKED=1 +fi + + fi + done + ;; + esac +fi + +if test "x$DBLINKED" = "x0"; then + DBVERS=0 + if test "x$enable_db" = "xyes"; then + { echo "$as_me:$LINENO: WARNING: cache support disabled (Berkeley DB is missing)." >&5 +echo "$as_me: WARNING: cache support disabled (Berkeley DB is missing)." >&2;} + fi +fi + + +cat >>confdefs.h <<_ACEOF +#define DBVERS $DBVERS +_ACEOF + + + +# Check whether --enable-threads was given. +if test "${enable_threads+set}" = set; then + enableval=$enable_threads; +else + enable_threads=yes +fi + + +if test "x$enable_threads" = "xyes"; then + +for ac_header in pthread.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +else + { { echo "$as_me:$LINENO: error: pthread support required" >&5 +echo "$as_me: error: pthread support required" >&2;} + { (exit 1); exit 1; }; } +fi + +done + + CPPFLAGS="$CPPFLAGS -D_REENTRANT" + checkpthread=yes + + { echo "$as_me:$LINENO: checking for pthread_create with libc" >&5 +echo $ECHO_N "checking for pthread_create with libc... $ECHO_C" >&6; } + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +pthread_create(); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + pthflag=yes; checkpthread=no +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + pthflag=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + { echo "$as_me:$LINENO: result: $pthflag" >&5 +echo "${ECHO_T}$pthflag" >&6; } + + for flag in "pthreads" "pthread"; do + if test "x$checkpthread" = "xyes"; then + { echo "$as_me:$LINENO: checking for pthread_create with -$flag" >&5 +echo $ECHO_N "checking for pthread_create with -$flag... $ECHO_C" >&6; } + OLDFLAGS="$LDFLAGS" + LDFLAGS="-$flag $LDFLAGS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +pthread_create(); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + pthflag=yes; checkpthread=no +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + pthflag=no; LDFLAGS="$OLDCFLAGS" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + { echo "$as_me:$LINENO: result: $pthflag" >&5 +echo "${ECHO_T}$pthflag" >&6; } + fi + done + + for lib in "c_r" "pthread"; do + if test "x$checkpthread" = "xyes"; then + case "x$LIBS" in + *-l$lib*);; + *) as_ac_Lib=`echo "ac_cv_lib_$lib''_pthread_create" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for pthread_create in -l$lib" >&5 +echo $ECHO_N "checking for pthread_create in -l$lib... $ECHO_C" >&6; } +if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$lib $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_create (); +int +main () +{ +return pthread_create (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Lib=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Lib=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +ac_res=`eval echo '${'$as_ac_Lib'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Lib'}'` = yes; then + LIBS="$LIBS -l$lib"; checkpthread=no +fi + ;; + esac + fi + done + + if test "x$checkpthread" = "xyes"; then + { echo "$as_me:$LINENO: checking for pthread_create" >&5 +echo $ECHO_N "checking for pthread_create... $ECHO_C" >&6; } +if test "${ac_cv_func_pthread_create+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define pthread_create to an innocuous variant, in case <limits.h> declares pthread_create. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define pthread_create innocuous_pthread_create + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char pthread_create (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef pthread_create + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_create (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_pthread_create || defined __stub___pthread_create +choke me +#endif + +int +main () +{ +return pthread_create (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_pthread_create=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_pthread_create=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_pthread_create" >&5 +echo "${ECHO_T}$ac_cv_func_pthread_create" >&6; } +if test $ac_cv_func_pthread_create = yes; then + checkpthread=no +fi + + text "x$checkpthread" = "xyes" && { { echo "$as_me:$LINENO: error: pthread library required" >&5 +echo "$as_me: error: pthread library required" >&2;} + { (exit 1); exit 1; }; } + fi + +cat >>confdefs.h <<\_ACEOF +#define LIBETPAN_REENTRANT 1 +_ACEOF + + LIBSUFFIX= + REENTRANT=1 +else + REENTRANT=0 + LIBSUFFIX=-no-mt +fi + + + + +{ echo "$as_me:$LINENO: checking for lockfile_create in -llockfile" >&5 +echo $ECHO_N "checking for lockfile_create in -llockfile... $ECHO_C" >&6; } +if test "${ac_cv_lib_lockfile_lockfile_create+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llockfile $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char lockfile_create (); +int +main () +{ +return lockfile_create (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_lockfile_lockfile_create=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_lockfile_lockfile_create=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_lockfile_lockfile_create" >&5 +echo "${ECHO_T}$ac_cv_lib_lockfile_lockfile_create" >&6; } +if test $ac_cv_lib_lockfile_lockfile_create = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBLOCKFILE 1 +_ACEOF + + LIBS="-llockfile $LIBS" + +fi + + + +cat >>confdefs.h <<_ACEOF +#define LIBETPAN_VERSION_MAJOR $VERSION_MAJOR +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LIBETPAN_VERSION_MINOR $VERSION_MINOR +_ACEOF + + + + + +# Check whether --with-sasl was given. +if test "${with_sasl+set}" = set; then + withval=$with_sasl; +else + with_sasl=yes +fi + +if test "x$with_sasl" != "xno"; then + OCPPFLAGS="$CPPFLAGS" + OLDFLAGS="$LDFLAGS" + if test "x$with_sasl" != "xyes" ; then + CPPFLAGS="$CPPFLAGS -I$with_sasl/include" + LDFLAGS="$LDFLAGS -L$with_sasl/lib" + fi + with_sasl=no + SASLLIBS="" + if test "${ac_cv_header_sasl_sasl_h+set}" = set; then + { echo "$as_me:$LINENO: checking for sasl/sasl.h" >&5 +echo $ECHO_N "checking for sasl/sasl.h... $ECHO_C" >&6; } +if test "${ac_cv_header_sasl_sasl_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_sasl_sasl_h" >&5 +echo "${ECHO_T}$ac_cv_header_sasl_sasl_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking sasl/sasl.h usability" >&5 +echo $ECHO_N "checking sasl/sasl.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <sasl/sasl.h> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking sasl/sasl.h presence" >&5 +echo $ECHO_N "checking sasl/sasl.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sasl/sasl.h> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: sasl/sasl.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: sasl/sasl.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sasl/sasl.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: sasl/sasl.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: sasl/sasl.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: sasl/sasl.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sasl/sasl.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: sasl/sasl.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sasl/sasl.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: sasl/sasl.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: sasl/sasl.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: sasl/sasl.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: sasl/sasl.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: sasl/sasl.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: sasl/sasl.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: sasl/sasl.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for sasl/sasl.h" >&5 +echo $ECHO_N "checking for sasl/sasl.h... $ECHO_C" >&6; } +if test "${ac_cv_header_sasl_sasl_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_sasl_sasl_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_sasl_sasl_h" >&5 +echo "${ECHO_T}$ac_cv_header_sasl_sasl_h" >&6; } + +fi +if test $ac_cv_header_sasl_sasl_h = yes; then + + { echo "$as_me:$LINENO: checking for sasl_client_init in -lsasl2" >&5 +echo $ECHO_N "checking for sasl_client_init in -lsasl2... $ECHO_C" >&6; } +if test "${ac_cv_lib_sasl2_sasl_client_init+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsasl2 $SASLLIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sasl_client_init (); +int +main () +{ +return sasl_client_init (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_sasl2_sasl_client_init=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_sasl2_sasl_client_init=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_sasl2_sasl_client_init" >&5 +echo "${ECHO_T}$ac_cv_lib_sasl2_sasl_client_init" >&6; } +if test $ac_cv_lib_sasl2_sasl_client_init = yes; then + with_sasl=yes +fi + +fi + + + if test "x$with_sasl" != "xyes"; then + CPPFLAGS="$OCPPFLAGS" + LDFLAGS="$OLDFLAGS" + fi +fi +if test "x$with_sasl" = "xyes"; then + +cat >>confdefs.h <<\_ACEOF +#define USE_SASL 1 +_ACEOF + + SASLLIBS="-lsasl2 $SASLLIBS" +else + { echo "$as_me:$LINENO: WARNING: SASL support disabled." >&5 +echo "$as_me: WARNING: SASL support disabled." >&2;} + SASLLIBS="" +fi + + +# Check whether --enable-ipv6 was given. +if test "${enable_ipv6+set}" = set; then + enableval=$enable_ipv6; +else + enable_ipv6=yes +fi + +{ echo "$as_me:$LINENO: checking whether to use IPv6" >&5 +echo $ECHO_N "checking whether to use IPv6... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $enable_ipv6" >&5 +echo "${ECHO_T}$enable_ipv6" >&6; } +if test "x$enable_ipv6" = "xyes"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_IPV6 1 +_ACEOF + + + { echo "$as_me:$LINENO: checking for IPv6 support" >&5 +echo $ECHO_N "checking for IPv6 support... $ECHO_C" >&6; } + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define INET6 + #include <sys/types.h> + #include <netinet/in.h> +int +main () +{ +int x = IPPROTO_IPV6; struct in6_addr a; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ipv6_support=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ipv6_support=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { echo "$as_me:$LINENO: result: $ipv6_support" >&5 +echo "${ECHO_T}$ipv6_support" >&6; } + + if test "x$ipv6_support" = "xyes"; then + + for func in "getaddrinfo" "freeaddrinfo"; do + { echo "$as_me:$LINENO: checking for $func" >&5 +echo $ECHO_N "checking for $func... $ECHO_C" >&6; } + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +$func(); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + func_present=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + func_present=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + { echo "$as_me:$LINENO: result: $func_present" >&5 +echo "${ECHO_T}$func_present" >&6; } + + if test "x$func_present" = "xno"; then + { { echo "$as_me:$LINENO: error: $func function required for IPv6 support" >&5 +echo "$as_me: error: $func function required for IPv6 support" >&2;} + { (exit 1); exit 1; }; } + fi + done + + else + { { echo "$as_me:$LINENO: error: cannot enable IPv6 support" >&5 +echo "$as_me: error: cannot enable IPv6 support" >&2;} + { (exit 1); exit 1; }; } + fi +fi + + +VERSION="$VERSION_MAJOR.$VERSION_MINOR" +test -d CVS && VERSION="$VERSION-dev-"`date +'%Y%m%d'` + +cat >>confdefs.h <<_ACEOF +#define LIBETPAN_VERSION "$VERSION" +_ACEOF + + + + +ac_config_files="$ac_config_files Makefile Rules libetpan-config src/Makefile src/main/libetpan_version.h" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { echo "$as_me:$LINENO: updating cache $cache_file" >&5 +echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 +echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +# Find out whether ``test -x'' works. Don't use a zero-byte file, as +# systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + as_executable_p="test -x" +else + as_executable_p=: +fi +rm -f conf$$.file + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 + +# Save the log message, to keep $[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.60a. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to <bug-autoconf@gnu.org>." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.60a, + with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2006 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + echo "$ac_cs_version"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + { echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + CONFIG_SHELL=$SHELL + export CONFIG_SHELL + exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "Rules") CONFIG_FILES="$CONFIG_FILES Rules" ;; + "libetpan-config") CONFIG_FILES="$CONFIG_FILES libetpan-config" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "src/main/libetpan_version.h") CONFIG_FILES="$CONFIG_FILES src/main/libetpan_version.h" ;; + + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +# +# Set up the sed scripts for CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "$CONFIG_FILES"; then + +_ACEOF + + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +SHELL!$SHELL$ac_delim +PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim +PACKAGE_NAME!$PACKAGE_NAME$ac_delim +PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim +PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim +PACKAGE_STRING!$PACKAGE_STRING$ac_delim +PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim +exec_prefix!$exec_prefix$ac_delim +prefix!$prefix$ac_delim +program_transform_name!$program_transform_name$ac_delim +bindir!$bindir$ac_delim +sbindir!$sbindir$ac_delim +libexecdir!$libexecdir$ac_delim +datarootdir!$datarootdir$ac_delim +datadir!$datadir$ac_delim +sysconfdir!$sysconfdir$ac_delim +sharedstatedir!$sharedstatedir$ac_delim +localstatedir!$localstatedir$ac_delim +includedir!$includedir$ac_delim +oldincludedir!$oldincludedir$ac_delim +docdir!$docdir$ac_delim +infodir!$infodir$ac_delim +htmldir!$htmldir$ac_delim +dvidir!$dvidir$ac_delim +pdfdir!$pdfdir$ac_delim +psdir!$psdir$ac_delim +libdir!$libdir$ac_delim +localedir!$localedir$ac_delim +mandir!$mandir$ac_delim +DEFS!$DEFS$ac_delim +ECHO_C!$ECHO_C$ac_delim +ECHO_N!$ECHO_N$ac_delim +ECHO_T!$ECHO_T$ac_delim +LIBS!$LIBS$ac_delim +build_alias!$build_alias$ac_delim +host_alias!$host_alias$ac_delim +target_alias!$target_alias$ac_delim +API_VERSION!$API_VERSION$ac_delim +CC!$CC$ac_delim +CFLAGS!$CFLAGS$ac_delim +LDFLAGS!$LDFLAGS$ac_delim +CPPFLAGS!$CPPFLAGS$ac_delim +ac_ct_CC!$ac_ct_CC$ac_delim +EXEEXT!$EXEEXT$ac_delim +OBJEXT!$OBJEXT$ac_delim +build!$build$ac_delim +build_cpu!$build_cpu$ac_delim +build_vendor!$build_vendor$ac_delim +build_os!$build_os$ac_delim +host!$host$ac_delim +host_cpu!$host_cpu$ac_delim +host_vendor!$host_vendor$ac_delim +host_os!$host_os$ac_delim +GREP!$GREP$ac_delim +EGREP!$EGREP$ac_delim +LN_S!$LN_S$ac_delim +ECHO!$ECHO$ac_delim +AR!$AR$ac_delim +RANLIB!$RANLIB$ac_delim +STRIP!$STRIP$ac_delim +CPP!$CPP$ac_delim +CXX!$CXX$ac_delim +CXXFLAGS!$CXXFLAGS$ac_delim +ac_ct_CXX!$ac_ct_CXX$ac_delim +CXXCPP!$CXXCPP$ac_delim +F77!$F77$ac_delim +FFLAGS!$FFLAGS$ac_delim +ac_ct_F77!$ac_ct_F77$ac_delim +LIBTOOL!$LIBTOOL$ac_delim +SET_MAKE!$SET_MAKE$ac_delim +INSTALL!$INSTALL$ac_delim +SSLLIBS!$SSLLIBS$ac_delim +GNUTLSLIB!$GNUTLSLIB$ac_delim +LIBICONV!$LIBICONV$ac_delim +DBLIB!$DBLIB$ac_delim +LIBSUFFIX!$LIBSUFFIX$ac_delim +REENTRANT!$REENTRANT$ac_delim +VERSION_MAJOR!$VERSION_MAJOR$ac_delim +VERSION_MINOR!$VERSION_MINOR$ac_delim +SASLLIBS!$SASLLIBS$ac_delim +VERSION!$VERSION$ac_delim +LIBOBJS!$LIBOBJS$ac_delim +LTLIBOBJS!$LTLIBOBJS$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 83; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS <conf$$subs.sed +rm -f conf$$subs.sed +cat >>$CONFIG_STATUS <<_ACEOF +:end +s/|#_!!_#|//g +CEOF$ac_eof +_ACEOF + + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF +fi # test -n "$CONFIG_FILES" + + +for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 +echo "$as_me: error: Invalid tag $ac_tag." >&2;} + { (exit 1); exit 1; }; };; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 +echo "$as_me: error: cannot find input file: $ac_f" >&2;} + { (exit 1); exit 1; }; };; + esac + ac_file_inputs="$ac_file_inputs $ac_f" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input="Generated from "`IFS=: + echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + fi + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin";; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= + +case `sed -n '/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p +' $ac_file_inputs` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s&@configure_input@&$configure_input&;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out"; rm -f "$tmp/out";; + *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; + esac + ;; + :H) + # + # CONFIG_HEADER + # +_ACEOF + +# Transform confdefs.h into a sed script `conftest.defines', that +# substitutes the proper values into config.h.in to produce config.h. +rm -f conftest.defines conftest.tail +# First, append a space to every undef/define line, to ease matching. +echo 's/$/ /' >conftest.defines +# Then, protect against being on the right side of a sed subst, or in +# an unquoted here document, in config.status. If some macros were +# called several times there might be several #defines for the same +# symbol, which is useless. But do not sort them, since the last +# AC_DEFINE must be honored. +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where +# NAME is the cpp macro being defined, VALUE is the value it is being given. +# PARAMS is the parameter list in the macro definition--in most cases, it's +# just an empty string. +ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*' +ac_dB='\\)[ (].*,\\1define\\2' +ac_dC=' ' +ac_dD=' ,' + +uniq confdefs.h | + sed -n ' + t rset + :rset + s/^[ ]*#[ ]*define[ ][ ]*// + t ok + d + :ok + s/[\\&,]/\\&/g + s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p + s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p + ' >>conftest.defines + +# Remove the space that was appended to ease matching. +# Then replace #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +# (The regexp can be short, since the line contains either #define or #undef.) +echo 's/ $// +s,^[ #]*u.*,/* & */,' >>conftest.defines + +# Break up conftest.defines: +ac_max_sed_lines=50 + +# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1" +# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2" +# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1" +# et cetera. +ac_in='$ac_file_inputs' +ac_out='"$tmp/out1"' +ac_nxt='"$tmp/out2"' + +while : +do + # Write a here document: + cat >>$CONFIG_STATUS <<_ACEOF + # First, check the format of the line: + cat >"\$tmp/defines.sed" <<\\CEOF +/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def +/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def +b +:def +_ACEOF + sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS + ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in + sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail + grep . conftest.tail >/dev/null || break + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines conftest.tail + +echo "ac_result=$ac_in" >>$CONFIG_STATUS +cat >>$CONFIG_STATUS <<\_ACEOF + if test x"$ac_file" != x-; then + echo "/* $configure_input */" >"$tmp/config.h" + cat "$ac_result" >>"$tmp/config.h" + if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f $ac_file + mv "$tmp/config.h" $ac_file + fi + else + echo "/* $configure_input */" + cat "$ac_result" + fi + rm -f "$tmp/out12" + ;; + + + esac + +done # for ac_tag + + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + + +cp -f src/main/libetpan_version.h build-windows Added: freeswitch/trunk/libs/libetpan/configure.in ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/configure.in Wed Dec 20 15:28:56 2006 @@ -0,0 +1,483 @@ +dnl Process this file with autoconf to create configure +dnl $Id: configure.in,v 1.68 2006/10/26 18:02:59 alfie Exp $ + +AC_INIT(src/main/libetpan_version.h.in) + +dnl Version major and minor +VERSION_MAJOR=0 +VERSION_MINOR=48 + +dnl API version +dnl 1. If you have changed any of the sources for this library, the revision +dnl number must be incremented. This is a new revision of the current +dnl interface. +dnl 2. If the interface has changed, then current must be incremented, and +dnl revision reset to `0'. This is the first revision of a new interface. +dnl 3. If the new interface is a superset of the previous interface (that is, +dnl if the previous interface has not been broken by the changes in this new +dnl release), then age must be incremented. This release is backwards +dnl compatible with the previous release. +dnl 4. If the new interface has removed elements with respect to the previous +dnl interface, then you have broken backward compatibility and age must be +dnl reset to `0'. This release has a new, but backwards incompatible +dnl interface. +API_CURRENT=10 +API_REVISION=0 +API_COMPATIBILITY=10 + +API_AGE=`expr $API_CURRENT - $API_COMPATIBILITY` +API_VERSION="$API_CURRENT:$API_REVISION:$API_AGE" +AC_SUBST(API_VERSION) + +AC_ARG_ENABLE(debug, [ --enable-debug setup flags (gcc) for debugging (default=no)], +CFLAGS="$CFLAGS -O2 -g" +CPPFLAGS="$CPPFLAGS -DDEBUG" +LDFLAGS="$LDFLAGS",) +AC_ARG_ENABLE(optim, [ --enable-optim setup flags (gcc) for optimizations (default=no)], +if test "x$enable_debug" != "xyes" ; then + CFLAGS="$CFLAGS -O2 -ffast-math -funroll-loops -g0" + CPPFLAGS="$CPPFLAGS" + LDFLAGS="$LDFLAGS -s" +else + AC_MSG_WARN([enable-optim and enable-debug are incompatible -- disabling optimizations]) +fi,) +CFLAGS="$CFLAGS -W -Wall" +AC_ARG_ENABLE(syntax, [ --enable-unstrict-syntax be lazy on syntax checking for protocols (default=no)], , [AC_DEFINE(UNSTRICT_SYNTAX, 1, [Define to be lazy on protocol syntax])]) + +AC_CONFIG_HEADER(config.h) + +AH_VERBATIM([CONFIG_H_FIRST], [/* Check for Linux's /usr/include/features.h + */ +#ifdef _FEATURES_H +# error config.h must be first file included +#endif]) + +AC_C_INLINE + +dnl Programs +AC_PROG_CC +AC_PROG_LIBTOOL +AC_PROG_MAKE_SET + +dnl Can't use AC_PROG_INSTALL +INSTALL='$(SHELL) $(top_builddir)/install-sh -c' +AC_SUBST(INSTALL) + +dnl Headers +AC_HEADER_STDC +AC_CHECK_HEADERS(fcntl.h unistd.h ctype.h sys/types.h sys/stat.h sys/mman.h limits.h) +AC_CHECK_HEADERS(netdb.h netinet/in.h sys/socket.h) +AC_CHECK_HEADERS(sys/param.h sys/select.h inttypes.h) + +dnl Functions +AC_FUNC_MMAP + +dnl Network libs +AC_CHECK_FUNC(connect, checksocket=no, checksocket=yes) +if test "x$checksocket" = "xyes"; then +case "x$LIBS" in + *-lsocket*);; + *) AC_CHECK_LIB(socket, connect) ;; +esac +fi +AC_CHECK_FUNC(inet_ntoa, checknsl=no, checknsl=yes) +if test "x$checknsl" = "xyes"; then +case "x$LIBS" in + *-lnsl*);; + *) AC_CHECK_LIB(nsl, inet_ntoa) ;; +esac +fi + +dnl OpenSSL -- very primitive right now +AC_ARG_WITH(openssl, [ --with-openssl[=DIR] include OpenSSL support (default=auto)], + [], [with_openssl=yes]) +if test "x$with_openssl" != "xno"; then + OCPPFLAGS="$CPPFLAGS" + OLDFLAGS="$LDFLAGS" + if test "x$with_openssl" != "xyes" ; then + CPPFLAGS="$CPPFLAGS -I$with_openssl/include" + LDFLAGS="$LDFLAGS -L$with_openssl/lib" + fi + with_openssl=no + SSLLIBS="" + AC_CHECK_HEADER(openssl/ssl.h, [ + AC_CHECK_LIB(rsaref, main, [SSLLIBS="-lrsaref"]) + AC_CHECK_LIB(crypto, main, [SSLLIBS="-lcrypto $SSLLIBS"], [], [$SSLLIBS]) + AC_CHECK_LIB(ssl, SSL_library_init, with_openssl=yes, [], [$SSLLIBS])]) + if test "x$with_openssl" != "xyes"; then + CPPFLAGS="$OCPPFLAGS" + LDFLAGS="$OLDFLAGS" + else + with_gnutls="no" + fi +fi +if test "x$with_openssl" = "xyes"; then + AC_DEFINE([USE_SSL], 1, [Define to use OpenSSL]) + SSLLIBS="-lssl $SSLLIBS" +else + SSLLIBS="" +fi +AC_SUBST(SSLLIBS) + +dnl GNUTLS +AC_ARG_WITH(gnutls, [ --with-gnutls[=DIR] include GnuTLS support (default=auto)], + [], [with_gnutls=no]) +if test "x$with_gnutls" != "xno"; then + OCPPFLAGS="$CPPFLAGS" + OLDFLAGS="$LDFLAGS" + if test "x$with_gnutls" != "xyes" ; then + CPPFLAGS="CRPPFLAGS -I$with_gnutls/include" + LDFLAGS="$LDFLAGS -L$with_gnutls/lib" + fi + GNUTLSLIB="" + AC_CHECK_HEADER(gnutls/gnutls.h, [ + AC_CHECK_LIB(gnutls, gnutls_global_deinit, with_gnutls=yes, [GNUTLSLIB="-lgnutls"]) + ]) + if test "x$with_gnutls" != "xyes"; then + CPPFLAGS="$OCPPFLAGS" + LDFLAGS="$OLDFLAGS" + else + with_openssl="no" + fi +fi +if test "x$with_gnutls" = "xyes"; then + AC_DEFINE([USE_GNUTLS],1, [Define to use GnuTLS]) + AC_DEFINE([USE_SSL], 1, [Define to use OpenSSL]) + GNUTLSLIB="-lgnutls" +else + GNUTLSLIB="" +fi +AC_SUBST(GNUTLSLIB) + +if test "x$with_openssl" = "xno"; then + if test "x$with_gnutls" = "xno"; then + AC_MSG_WARN([OpenSSL support disabled.]) + fi +fi + +dnl iconv +LIBICONV="" + +AC_ARG_ENABLE(iconv, + [ --disable-iconv make a version not using iconv], + enable_iconv=no, enable_iconv=yes) +if test x$enable_iconv = xyes; then + dnl get prototype + AC_CHECK_HEADER(iconv.h, [ICONV_HEADER=1], [ICONV_HEADER=0]) + + ICONV_PROTO=no + AC_MSG_CHECKING([checking iconv() prototype]) + if test "x$ICONV_HEADER" = x1 ; then + SAVED_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="-std=c99 $CPPFLAGS" + AC_TRY_COMPILE([#include <iconv.h> + size_t iconv (iconv_t cd, char ** restrict inbuf, + size_t * restrict inbytesleft, + char ** restrict outbuf, + size_t * restrict outbytesleft);], + [], + [ICONV_PROTO=noconst] + []) + AC_TRY_COMPILE([#include <iconv.h> + size_t iconv (iconv_t cd, const char ** restrict inbuf, + size_t * restrict inbytesleft, + char ** restrict outbuf, + size_t * restrict outbytesleft);], + [], + [ICONV_PROTO=const] + []) + CPPFLAGS="$SAVED_CPPFLAGS" + fi + + dnl try to link + ICONV_LINKED=NO + if test "$ICONV_PROTO" != "xno" ; then + AC_MSG_RESULT([ok]) + + AC_MSG_CHECKING([for iconv]) + + ICONV_LINKED=0 + AC_TRY_LINK([#include <stdlib.h> +#include <iconv.h>], + [iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);], + [ICONV_LINKED=1], + []) + for lib in iconv ; do + if test "x$ICONV_LINKED" = "x0" ; then + LIBS=-l$lib + AC_TRY_LINK([#include <stdlib.h> +#include <iconv.h>], + [iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);], + [LIBICONV="$LIBS" ; ICONV_LINKED=1], + []) + fi + done + LIBS="" + + if test "x$ICONV_LINKED" = "x1" ; then + AC_MSG_RESULT([found]) + else + AC_MSG_RESULT([not found]) + fi + else + AC_MSG_RESULT([failed]) + fi + + if test "x$ICONV_LINKED" = "x1" ; then + AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.]) + fi + + ICONV_PROTO_CONST=0 + if test "x$ICONV_PROTO" = "xconst" ; then + AC_DEFINE_UNQUOTED(HAVE_ICONV_PROTO_CONST, 1, + [prototype of iconv() has const parameters]) + fi +fi +AC_SUBST(LIBICONV) + +dnl Berkeley DB + +DBVERS=0 +DBLINKED=0 +DBLIB="" + +AC_ARG_ENABLE(db, [ --disable-db disable Berkeley DB (default=try to detect DB)],[enable_db=$enableval],[enable_db=yes]) + +dnl Check for a presence of Berkeley DB header +if test "x$enable_db" != "xyes"; then + AC_MSG_WARN(cache support disabled) +else + AC_CHECK_HEADER(db.h, [DB_HEADER=1], [DB_HEADER=0]) +fi + +if test "x$DB_HEADER" = "x1"; then +dnl Check for version of Berkeley DB + AC_MSG_CHECKING([version of Berkeley DB]) + +dnl check for version 3 and above + AC_TRY_COMPILE( + [#include <db.h>], + [#if DB_VERSION_MAJOR < 3 + #error DB version 3 or above needed + #endif], + [DBVERS=3] + []) + +dnl check for version 2 + if test "x$DBVERS" = "x0"; then + AC_TRY_COMPILE([#include <db.h>], + [#if DB_VERSION_MAJOR != 2 + #error DB version 2 needed + #endif], + [DBVERS=2] + []) + fi + + if test "x$DBVERS" = "x0"; then +dnl assume version 1 + DBVERS=1 + fi + +dnl test linkage with Berkeley DB + +dnl Look for db3 or superior with db_create call + case "$DBVERS" in + 3) + AC_MSG_RESULT([version 3.x or above]) + for lib in db-4.4 db-4.3 db-4.2 db-4.1 db-4.0 db-4 db4 db-3.2 db-3 db3 db; do + if test "x$DBLINKED" = "x0"; then +dnl AC_CHECK_LIB($lib, db_create, [DBLIB="-l$lib"; DBLINKED=1], []) +dnl installations of libdb4 function names are defined in db.h +dnl to other symbols + AC_MSG_CHECKING([for db_create() in -l$lib]) + LIBS=-l$lib + AC_TRY_LINK( + [#include <db.h>], + [db_create(0,0,0)], + [DBLIB="-l$lib"; DBLINKED=1; AC_MSG_RESULT([found])], + [AC_MSG_RESULT([not found])]) + fi + done + LIBS="" + ;; + +dnl Look for db2 with db_open call + 2) + AC_MSG_RESULT([version 2.x]) + for lib in db2 db; do + if test "x$DBLINKED" = "x0"; then + AC_CHECK_LIB($lib, db_open, [DBLIB="-l$lib"; DBLINKED=1], []) + fi + done + ;; + + *) +dnl Look for db1 with dbopen call in -ldb or in libc (bsds) + AC_MSG_RESULT([version 1.x]) + AC_CHECK_FUNC(dbopen, [DBLINKED=1], []) + for lib in db-1 db1 db; do + if test "x$DBLINKED" = "x0"; then + AC_CHECK_LIB($lib, dbopen, [DBLIB="-l$lib"; DBLINKED=1], []) + fi + done + ;; +dnl fi + esac +fi + +if test "x$DBLINKED" = "x0"; then + DBVERS=0 + if test "x$enable_db" = "xyes"; then + AC_MSG_WARN(cache support disabled (Berkeley DB is missing).) + fi +fi + +AC_DEFINE_UNQUOTED(DBVERS, $DBVERS, + [Define to detected Berkeley DB major version number]) +AC_SUBST(DBLIB) + +dnl Threading support, if enabled +AC_ARG_ENABLE(threads, [ --disable-threads do not include multithreading support using pthread],,[enable_threads=yes]) + +if test "x$enable_threads" = "xyes"; then + dnl Try to find a good CFLAGS/LDFLAGS for pthreads + AC_CHECK_HEADERS(pthread.h, [], [AC_MSG_ERROR([pthread support required])]) + CPPFLAGS="$CPPFLAGS -D_REENTRANT" + checkpthread=yes + + AC_MSG_CHECKING([for pthread_create with libc]) + AC_TRY_LINK([], [pthread_create();], + [pthflag=yes; checkpthread=no], + [pthflag=no]) + AC_MSG_RESULT($pthflag) + + for flag in "pthreads" "pthread"; do + if test "x$checkpthread" = "xyes"; then + AC_MSG_CHECKING([for pthread_create with -$flag]) + OLDFLAGS="$LDFLAGS" + LDFLAGS="-$flag $LDFLAGS" + AC_TRY_LINK([], [pthread_create();], + [pthflag=yes; checkpthread=no], + [pthflag=no; LDFLAGS="$OLDCFLAGS"]) + AC_MSG_RESULT($pthflag) + fi + done + + for lib in "c_r" "pthread"; do + if test "x$checkpthread" = "xyes"; then + case "x$LIBS" in + *-l$lib*);; + *) AC_CHECK_LIB($lib, pthread_create, [LIBS="$LIBS -l$lib"; checkpthread=no]) ;; + esac + fi + done + + if test "x$checkpthread" = "xyes"; then + AC_CHECK_FUNC(pthread_create, checkpthread=no) + text "x$checkpthread" = "xyes" && AC_MSG_ERROR([pthread library required]) + fi + AC_DEFINE([LIBETPAN_REENTRANT], 1, [Define to include multithreading support]) + LIBSUFFIX= + REENTRANT=1 +else + REENTRANT=0 + LIBSUFFIX=-no-mt +fi +AC_SUBST(LIBSUFFIX) +AC_SUBST(REENTRANT) + +dnl liblockfile on debian systems +AC_CHECK_LIB(lockfile, lockfile_create) + +AC_DEFINE_UNQUOTED(LIBETPAN_VERSION_MAJOR, $VERSION_MAJOR, + [Define this to the major version of libEtPan]) +AC_DEFINE_UNQUOTED(LIBETPAN_VERSION_MINOR, $VERSION_MINOR, + [Define this to the minor version of libEtPan]) +AC_SUBST(VERSION_MAJOR) +AC_SUBST(VERSION_MINOR) + +dnl Cyrus SASL +AC_ARG_WITH(sasl, [ --with-sasl[=DIR] include SASL support (default=auto)], + [], [with_sasl=yes]) +if test "x$with_sasl" != "xno"; then + OCPPFLAGS="$CPPFLAGS" + OLDFLAGS="$LDFLAGS" + if test "x$with_sasl" != "xyes" ; then + CPPFLAGS="$CPPFLAGS -I$with_sasl/include" + LDFLAGS="$LDFLAGS -L$with_sasl/lib" + fi + with_sasl=no + SASLLIBS="" + AC_CHECK_HEADER(sasl/sasl.h, [ + AC_CHECK_LIB(sasl2, sasl_client_init, with_sasl=yes, [], [$SASLLIBS])]) + if test "x$with_sasl" != "xyes"; then + CPPFLAGS="$OCPPFLAGS" + LDFLAGS="$OLDFLAGS" + fi +fi +if test "x$with_sasl" = "xyes"; then + AC_DEFINE([USE_SASL], 1, [Define to use SASL]) + SASLLIBS="-lsasl2 $SASLLIBS" +else + AC_MSG_WARN([SASL support disabled.]) + SASLLIBS="" +fi +AC_SUBST(SASLLIBS) + +dnl IPv6 support +AC_ARG_ENABLE(ipv6, AC_HELP_STRING([--disable-ipv6], [enable IPv6 support (default=yes)]), , enable_ipv6=yes) +AC_MSG_CHECKING([whether to use IPv6]) +AC_MSG_RESULT($enable_ipv6) +if test "x$enable_ipv6" = "xyes"; then + AC_DEFINE(HAVE_IPV6, 1, [Define to enable IPv6 support.]) + + dnl check for IPv6 support + AC_MSG_CHECKING([for IPv6 support]) + AC_TRY_COMPILE([#define INET6 + #include <sys/types.h> + #include <netinet/in.h>], + [int x = IPPROTO_IPV6; struct in6_addr a;], + ipv6_support=yes, ipv6_support=no) + AC_MSG_RESULT($ipv6_support) + + if test "x$ipv6_support" = "xyes"; then + + dnl check for getaddrinfo and freeaddrinfo function presence + for func in "getaddrinfo" "freeaddrinfo"; do + AC_MSG_CHECKING([for $func]) + AC_TRY_LINK([], [$func();], + [func_present=yes], + [func_present=no]) + AC_MSG_RESULT($func_present) + + if test "x$func_present" = "xno"; then + AC_MSG_ERROR([$func function required for IPv6 support]) + fi + done + + else + AC_MSG_ERROR([cannot enable IPv6 support]) + fi +fi + + +dnl Version +VERSION="$VERSION_MAJOR.$VERSION_MINOR" +test -d CVS && VERSION="$VERSION-dev-"`date +'%Y%m%d'` +AC_DEFINE_UNQUOTED(LIBETPAN_VERSION, "$VERSION", + [Define this to the version of libEtPan]) +AC_SUBST(VERSION) + + +AC_OUTPUT(Makefile \ + Rules \ + libetpan-config \ + src/Makefile \ + src/main/libetpan_version.h \ + ) + +cp -f src/main/libetpan_version.h build-windows Added: freeswitch/trunk/libs/libetpan/doc/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,6 @@ +API +API.html +API.txt +README +README.html +README.txt Added: freeswitch/trunk/libs/libetpan/doc/API.html ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API.html Wed Dec 20 15:28:56 2006 @@ -0,0 +1,22816 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>libEtPan! API</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"></HEAD +><BODY +CLASS="BOOK" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="BOOK" +><A +NAME="LIBETPAN-API" +></A +><DIV +CLASS="TITLEPAGE" +><H1 +CLASS="TITLE" +><A +NAME="AEN2" +>libEtPan! API</A +></H1 +><H3 +CLASS="AUTHOR" +><A +NAME="AEN6" +></A +>Viet Hoa DINH</H3 +><P +CLASS="COPYRIGHT" +>Copyright © 2003 DINH Viet Hoa</P +><HR></DIV +><DIV +CLASS="TOC" +><DL +><DT +><B +>Table of Contents</B +></DT +><DT +>1. <A +HREF="#AEN13" +>Introduction</A +></DT +><DT +>2. <A +HREF="#AEN16" +>Tools and datatypes</A +></DT +><DD +><DL +><DT +><A +HREF="#AEN19" +>Array</A +></DT +><DD +><DL +><DT +><A +HREF="#CARRAY-NEW" +>carray_new and carray_free</A +></DT +><DT +><A +HREF="#CARRAY-SET-SIZE" +>carray_set_size</A +></DT +><DT +><A +HREF="#CARRAY-COUNT" +>carray_count, carray_add, carray_get and carray_set</A +></DT +><DT +><A +HREF="#CARRAY-DELETE" +>carray_delete</A +></DT +><DT +><A +HREF="#CARRAY-DATA" +>carray_data</A +></DT +></DL +></DD +><DT +><A +HREF="#CLIST" +>List</A +></DT +><DD +><DL +><DT +><A +HREF="#CLIST-NEW" +>clist_new and clist_free</A +></DT +><DT +><A +HREF="#CLIST-COUNT" +>clist_isempty and clist_count</A +></DT +><DT +><A +HREF="#CLIST-BEGIN" +>running through clist</A +></DT +><DT +><A +HREF="#CLIST-APPEND" +>clist modification</A +></DT +><DT +><A +HREF="#CLIST-FOREACH" +>clist_foreach</A +></DT +><DT +><A +HREF="#CLIST-CONCAT" +>clist_concat</A +></DT +></DL +></DD +><DT +><A +HREF="#AEN161" +>Hash table</A +></DT +><DD +><DL +><DT +><A +HREF="#CHASH-NEW" +>chash_new and chash_free</A +></DT +><DT +><A +HREF="#CHASH-GET" +>chash_set and chash_get</A +></DT +><DT +><A +HREF="#CHASH-DELETE" +>chash_delete</A +></DT +><DT +><A +HREF="#CHASH-RESIZE" +>chash_resize</A +></DT +><DT +><A +HREF="#CHASH-BEGIN" +>running through the chash</A +></DT +><DT +><A +HREF="#CHASH-COUNT" +>chash_size and chash_count</A +></DT +></DL +></DD +><DT +><A +HREF="#AEN229" +>Buffered I/O</A +></DT +><DD +><DL +><DT +><A +HREF="#MAILSTREAM-SOCKET" +>socket stream</A +></DT +><DT +><A +HREF="#MAILSTREAM-SSL" +>TLS stream</A +></DT +></DL +></DD +><DT +><A +HREF="#MAILSTREAM-LOW" +>non-buffered I/O</A +></DT +><DT +><A +HREF="#AEN312" +>strings</A +></DT +><DD +><DL +><DT +><A +HREF="#MMAP-STRING-NEW" +>constructor and destructor</A +></DT +><DT +><A +HREF="#MMAP-STRING-ASSIGN" +>string value modification</A +></DT +><DT +><A +HREF="#MMAP-STRING-APPEND" +>insertion in string, deletion in string</A +></DT +><DT +><A +HREF="#MMAP-STRING-REF" +>referencing string</A +></DT +></DL +></DD +></DL +></DD +><DT +>3. <A +HREF="#IMF" +>Internet Message Format</A +></DT +><DD +><DL +><DT +><A +HREF="#AEN397" +>Quick start</A +></DT +><DD +><DL +><DT +><A +HREF="#AEN400" +>Parse message headers</A +></DT +><DT +><A +HREF="#AEN420" +>Render the message headers</A +></DT +></DL +></DD +><DT +><A +HREF="#AEN425" +>Data types</A +></DT +><DD +><DL +><DT +><A +HREF="#MAILIMF-MAILBOX" +>mailimf_mailbox - mailbox</A +></DT +><DT +><A +HREF="#MAILIMF-ADDRESS" +>mailimf_address - address</A +></DT +><DT +><A +HREF="#MAILIMF-MAILBOX-LIST" +>mailimf_mailbox_list - list of mailboxes</A +></DT +><DT +><A +HREF="#MAILIMF-ADDRESS-LIST" +>mailimf_address_list - list of addresses</A +></DT +><DT +><A +HREF="#MAILIMF-GROUP" +>mailimf_group - named group of mailboxes</A +></DT +><DT +><A +HREF="#MAILIMF-DATE-TIME" +>mailimf_date_time - date of a message</A +></DT +><DT +><A +HREF="#MAILIMF-ORIG-DATE" +>mailimf_orig_date - parsed content of date header</A +></DT +><DT +><A +HREF="#MAILIMF-FROM" +>mailimf_from - parsed content of From header</A +></DT +><DT +><A +HREF="#MAILIMF-SENDER" +>mailimf_sender - parsed content of Sender header</A +></DT +><DT +><A +HREF="#MAILIMF-REPLY-TO" +>mailimf_reply_to - parsed content of Reply-To header</A +></DT +><DT +><A +HREF="#MAILIMF-TO" +>mailimf_to - parsed content of To header</A +></DT +><DT +><A +HREF="#MAILIMF-CC" +>mailimf_cc - parsed content of Cc</A +></DT +><DT +><A +HREF="#MAILIMF-BCC" +>mailimf_bcc - parsed content of Bcc field</A +></DT +><DT +><A +HREF="#MAILIMF-MESSAGE-ID" +>mailimf_message_id - parsed content of Message-ID header</A +></DT +><DT +><A +HREF="#MAILIMF-IN-REPLY-TO" +>mailimf_in_reply_to - parsed content of In-Reply-To + field</A +></DT +><DT +><A +HREF="#MAILIMF-REFERENCES" +>mailimf_references - parsed content of References field</A +></DT +><DT +><A +HREF="#MAILIMF-SUBJECT" +>mailimf_subject - parsed content of Subject field</A +></DT +><DT +><A +HREF="#MAILIMF-COMMENTS" +>mailimf_comments - parsed content of Comments field</A +></DT +><DT +><A +HREF="#MAILIMF-KEYWORDS" +>mailimf_keywords - parsed content of Keywords field</A +></DT +><DT +><A +HREF="#MAILIMF-RETURN" +>mailimf_return - parsed content of Return-Path field</A +></DT +><DT +><A +HREF="#MAILIMF-PATH" +>mailimf_path - address in Return-Path field</A +></DT +><DT +><A +HREF="#MAILIMF-OPTIONAL-FIELD" +>mailimf_optional_field - non-standard header</A +></DT +><DT +><A +HREF="#MAILIMF-FIELD" +>mailimf_field - header field</A +></DT +><DT +><A +HREF="#MAILIMF-FIELDS" +>mailimf_fields - list of header fields</A +></DT +><DT +><A +HREF="#MAILIMF-BODY" +>mailimf_body - message body without headers</A +></DT +><DT +><A +HREF="#MAILIMF-MESSAGE" +>mailimf_message - parsed message</A +></DT +><DT +><A +HREF="#MAILIMF-SINGLE-FIELDS" +>mailimf_single_fields - simplified fields</A +></DT +></DL +></DD +><DT +><A +HREF="#AEN1094" +>Parser functions</A +></DT +><DD +><DL +><DT +><A +HREF="#MAILIMF-ADDRESS-LIST-PARSE" +>mailimf_address_list_parse</A +></DT +><DT +><A +HREF="#MAILIMF-ADDRESS-PARSE" +>mailimf_address_parse</A +></DT +><DT +><A +HREF="#MAILIMF-BODY-PARSE" +>mailimf_body_parse</A +></DT +><DT +><A +HREF="#MAILIMF-ENVELOPE-AND-OPTIONAL-FIELDS-PARSE" +>mailimf_envelope_and_optional_fields_parse</A +></DT +><DT +><A +HREF="#MAILIMF-ENVELOPE-FIELDS-PARSE" +>mailimf_envelope_fields_parse</A +></DT +><DT +><A +HREF="#MAILIMF-OPTIONAL-FIELDS-PARSE" +>mailimf_optional_fields_parse</A +></DT +><DT +><A +HREF="#MAILIMF-FIELDS-PARSE" +>mailimf_fields_parse</A +></DT +><DT +><A +HREF="#MAILIMF-IGNORE-FIELD-PARSE" +>mailimf_ignore_field_parse</A +></DT +><DT +><A +HREF="#MAILIMF-MAILBOX-LIST-PARSE" +>mailimf_mailbox_list_parse</A +></DT +><DT +><A +HREF="#MAILIMF-MAILBOX-PARSE" +>mailimf_mailbox_parse</A +></DT +><DT +><A +HREF="#MAILIMF-MESSAGE-PARSE" +>mailimf_message_parse</A +></DT +></DL +></DD +><DT +><A +HREF="#AEN1381" +>Creation functions</A +></DT +><DD +><DL +><DT +><A +HREF="#MAILIMF-MAILBOX-LIST-ADD" +>mailimf_mailbox_list</A +></DT +><DT +><A +HREF="#MAILIMF-ADDRESS-LIST-ADD" +>mailimf_address_list</A +></DT +><DT +><A +HREF="#MAILIMF-FIELDS-ADD" +>mailimf_fields</A +></DT +></DL +></DD +><DT +><A +HREF="#AEN1556" +>Rendering of messages</A +></DT +><DD +><DL +><DT +><A +HREF="#MAILIMF-FIELDS-WRITE" +>Header fields</A +></DT +></DL +></DD +></DL +></DD +><DT +>4. <A +HREF="#AEN1586" +>MIME</A +></DT +><DD +><DL +><DT +><A +HREF="#AEN1598" +>Quick start</A +></DT +><DD +><DL +><DT +><A +HREF="#AEN1601" +>Parse MIME message</A +></DT +><DT +><A +HREF="#AEN1609" +>Render the MIME message</A +></DT +></DL +></DD +><DT +><A +HREF="#AEN1614" +>Data types</A +></DT +><DD +><DL +><DT +><A +HREF="#MAILMIME-COMPOSITE-TYPE" +>mailmime_composite_type - Composite MIME type</A +></DT +><DT +><A +HREF="#MAILMIME-CONTENT" +>mailmime_content - MIME content type (Content-Type)</A +></DT +><DT +><A +HREF="#MAILMIME-DISCRETE-TYPE" +>mailmime_discrete_type - MIME discrete type</A +></DT +><DT +><A +HREF="#MAILMIME-FIELD" +>mailmime_field - MIME header field</A +></DT +><DT +><A +HREF="#MAILMIME-MECHANISM" +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</A +></DT +><DT +><A +HREF="#MAILMIME-FIELDS" +>mailmime_fields - header fields</A +></DT +><DT +><A +HREF="#MAILMIME-PARAMETER" +>mailmime_parameter - MIME type parameter</A +></DT +><DT +><A +HREF="#MAILMIME-TYPE" +>mailmime_type - MIME main type</A +></DT +><DT +><A +HREF="#MAILMIME-LANGUAGE" +>mailmime_language - Language of MIME part</A +></DT +><DT +><A +HREF="#MAILMIME-DATA" +>mailmime_data - Content of MIME part</A +></DT +><DT +><A +HREF="#MAILMIME" +>mailmime - MIME part</A +></DT +><DT +><A +HREF="#MAILMIME-DISPOSITION" +>mailmime_disposition - MIME disposition information (Content-Disposition)</A +></DT +><DT +><A +HREF="#MAILMIME-DISPOSITION-TYPE" +>mailmime_disposition_type - Type of MIME disposition</A +></DT +><DT +><A +HREF="#MAILMIME-DISPOSITION-PARM" +>mailmime_disposition_parm - MIME disposition parameter</A +></DT +><DT +><A +HREF="#MAILMIME-SINGLE-FIELDS" +>mailmime_single_fields - MIME headers</A +></DT +></DL +></DD +><DT +><A +HREF="#AEN2180" +>Parser functions</A +></DT +><DD +><DL +><DT +><A +HREF="#MAILMIME-CONTENT-PARSE" +>mailmime_content_parse</A +></DT +><DT +><A +HREF="#MAILMIME-DESCRIPTION-PARSE" +>mailmime_description_parse</A +></DT +><DT +><A +HREF="#MAILMIME-ENCODING-PARSE" +>mailmime_encoding_parse</A +></DT +><DT +><A +HREF="#MAILMIME-FIELD-PARSE" +>mailmime_field_parse</A +></DT +><DT +><A +HREF="#MAILMIME-ID-PARSE" +>mailmime_id_parse</A +></DT +><DT +><A +HREF="#MAILMIME-FIELDS-PARSE" +>mailmime_fields_parse</A +></DT +><DT +><A +HREF="#MAILMIME-VERSION-PARSE" +>mailmime_version_parse</A +></DT +><DT +><A +HREF="#MAILMIME-PARAMETER-PARSE" +>mailmime_parameter_parse</A +></DT +><DT +><A +HREF="#MAILMIME-LANGUAGE-PARSE" +>mailmime_language_parse</A +></DT +><DT +><A +HREF="#MAILMIME-DISPOSITION-PARSE" +>mailmime_disposition_parse</A +></DT +><DT +><A +HREF="#MAILMIME-DISPOSITION-TYPE-PARSE" +>mailmime_disposition_type_parse</A +></DT +><DT +><A +HREF="#MAILMIME-ENCODED-PHRASE-PARSE" +>mailmime_encoded_phrase_parse</A +></DT +><DT +><A +HREF="#MAILMIME-PARSE" +>mailmime_parse</A +></DT +><DT +><A +HREF="#MAILMIME-BASE64-BODY-PARSE" +>mailmime_base64_body_parse</A +></DT +><DT +><A +HREF="#MAILMIME-QUOTED-PRINTABLE-BODY-PARSE" +>mailmime_quoted_printable_body_parse</A +></DT +><DT +><A +HREF="#MAILMIME-BINARY-BODY-PARSE" +>mailmime_binary_body_parse</A +></DT +><DT +><A +HREF="#MAILMIME-PART-PARSE" +>mailmime_part_parse</A +></DT +></DL +></DD +><DT +><A +HREF="#AEN2583" +>Rendering of MIME parts</A +></DT +><DD +><DL +><DT +><A +HREF="#MAILMIME-FIELDS-WRITE" +>mailmime_fields_write, mailmime_content_write and + mailmime_content_type_write</A +></DT +><DT +><A +HREF="#MAILMIME-WRITE" +>mailmime_write</A +></DT +><DT +><A +HREF="#MAILMIME-QUOTED-PRINTABLE-WRITE" +>mailmime_quoted_printable_write + and mailmime_base64_write</A +></DT +><DT +><A +HREF="#MAILMIME-DATA-WRITE" +>mailmime_data_write</A +></DT +></DL +></DD +><DT +><A +HREF="#AEN2669" +>Creation functions</A +></DT +><DD +><DL +><DT +><A +HREF="#MAILMIME-DISPOSITION-NEW-FILENAME" +>mailmime_disposition_new_filename and + mailmime_disposition_new_with_data</A +></DT +><DT +><A +HREF="#MAILMIME-FIELDS-NEW-EMPTY" +>mailmime_fields_new_empty and mailmime_fields_add</A +></DT +><DT +><A +HREF="#MAILMIME-FIELDS-NEW-WITH-DATA" +>mailmime_fields_new_with_data and + mailmime_fields_new_with_version</A +></DT +><DT +><A +HREF="#MAILMIME-GET-CONTENT-MESSAGE" +>mailmime_get_content_message</A +></DT +><DT +><A +HREF="#MAILMIME-DATA-NEW-DATA" +>mailmime_data_new_data and mailmime_data_new_file</A +></DT +><DT +><A +HREF="#MAILMIME-NEW-MESSAGE-DATA" +>mailmime_new_message_data, mailmime_new_empty and + mailmime_new_with_content</A +></DT +><DT +><A +HREF="#MAILMIME-SET-PREAMBLE-FILE" +>mailmime_set_preamble_file, mailmime_set_epilogue_file, + mailmime_set_preamble_text and mailmime_set_epilogue_text</A +></DT +><DT +><A +HREF="#MAILMIME-SET-BODY-FILE" +>mailmime_set_body_file and mailmime_set_body_text</A +></DT +><DT +><A +HREF="#MAILMIME-ADD-PART" +>mailmime_add_part, mailmime_remove_part, + mailmime_smart_add_part and mailmime_smart_remove_part</A +></DT +><DT +><A +HREF="#MAILMIME-SET-IMF-FIELDS" +>mailmime_set_imf_fields</A +></DT +><DT +><A +HREF="#MAILMIME-FIELDS-NEW-ENCODING" +>mailmime_fields_new_encoding and + mailmime_fields_new_filename</A +></DT +></DL +></DD +><DT +><A +HREF="#AEN2946" +>Helper functions</A +></DT +><DD +><DL +><DT +><A +HREF="#MAILMIME-TRANSFER-ENCODING-GET" +>mailmime_transfer_encoding_get</A +></DT +><DT +><A +HREF="#MAILMIME-CONTENT-CHARSET-GET" +>mailmime_content_charset_get and + mailmime_content_param_get</A +></DT +></DL +></DD +></DL +></DD +><DT +>5. <A +HREF="#AEN2988" +>Storages, folders, messages</A +></DT +><DD +><DL +><DT +><A +HREF="#AEN2990" +>Introduction</A +></DT +><DD +><DL +><DT +><A +HREF="#AEN2993" +>Message</A +></DT +><DT +><A +HREF="#AEN2996" +>MIME part</A +></DT +><DT +><A +HREF="#AEN2999" +>Mailbox</A +></DT +><DT +><A +HREF="#AEN3002" +>Storage</A +></DT +><DT +><A +HREF="#AEN3005" +>Folder</A +></DT +><DT +><A +HREF="#AEN3008" +>Session</A +></DT +></DL +></DD +><DT +><A +HREF="#AEN3011" +>Error codes</A +></DT +><DT +><A +HREF="#AEN3015" +>Storage</A +></DT +><DD +><DL +><DT +><A +HREF="#MAILSTORAGE-DRIVER" +>Storage driver</A +></DT +><DT +><A +HREF="#MAILSTORAGE" +>Storage</A +></DT +><DT +><A +HREF="#MAILSTORAGE-NEW" +>mailstorage_new and mailstorage_free</A +></DT +><DT +><A +HREF="#MAILSTORAGE-CONNECT" +>mailstorage_connect and mailstorage_disconnect</A +></DT +><DT +><A +HREF="#AEN3074" +>IMAP storage</A +></DT +><DT +><A +HREF="#AEN3077" +>Example</A +></DT +></DL +></DD +><DT +><A +HREF="#AEN3082" +>Folder</A +></DT +><DD +><DL +><DT +><A +HREF="#MAILFOLDER-DRIVER" +>Folder driver</A +></DT +><DT +><A +HREF="#AEN3095" +>Folder</A +></DT +><DT +><A +HREF="#MAILFOLDER-NEW" +>mailfolder_new and mail_folder_free</A +></DT +><DT +><A +HREF="#MAILFOLDER-CONNECT" +>mailfolder_connect and mailfolder_disconnect</A +></DT +><DT +><A +HREF="#MAILFOLDER-NOOP" +>mailfolder_noop</A +></DT +><DT +><A +HREF="#MAILFOLDER-CHECK" +>mailfolder_check</A +></DT +><DT +><A +HREF="#MAILFOLDER-EXPUNGE" +>mailfolder_expunge</A +></DT +><DT +><A +HREF="#MAILFOLDER-STATUS" +>mailfolder_status</A +></DT +><DT +><A +HREF="#MAILFOLDER-APPEND-MESSAGE" +>mailfolder_append_message</A +></DT +><DT +><A +HREF="#MAILFOLDER-GET-MESSAGES-LIST" +>mailfolder_get_messages_list</A +></DT +><DT +><A +HREF="#MAILFOLDER-GET-ENVELOPES-LIST" +>mailfolder_get_envelopes_list</A +></DT +><DT +><A +HREF="#MAILFOLDER-GET-MESSAGE" +>mailfolder_get_message</A +></DT +><DT +><A +HREF="#MAILFOLDER-GET-MESSAGE-BY-UID" +>mailfolder_get_message_by_uid</A +></DT +><DT +><A +HREF="#AEN3193" +>Example</A +></DT +></DL +></DD +><DT +><A +HREF="#AEN3198" +>Message</A +></DT +><DD +><DL +><DT +><A +HREF="#MAILMESSAGE-DRIVER" +>Message driver</A +></DT +><DT +><A +HREF="#MAILMESSAGE" +>Message</A +></DT +><DT +><A +HREF="#MAILMESSAGE-NEW" +>mailmessage_new</A +></DT +><DT +><A +HREF="#MAILMESSAGE-INIT" +>mailmessage_init</A +></DT +><DT +><A +HREF="#MAILMESSAGE-FLUSH" +>mailmessage_flush</A +></DT +><DT +><A +HREF="#MAILMESSAGE-CHECK" +>mailmessage_check</A +></DT +><DT +><A +HREF="#MAILMESSAGE-FETCH-RESULT-FREE" +>mailmessage_fetch_result_free</A +></DT +><DT +><A +HREF="#MAILMESSAGE-FETCH" +>mailmessage_fetch</A +></DT +><DT +><A +HREF="#MAILMESSAGE-FETCH-HEADER" +>mailmessage_fetch_header</A +></DT +><DT +><A +HREF="#MAILMESSAGE-FETCH-BODY" +>mailmessage_fetch_body</A +></DT +><DT +><A +HREF="#MAILMESSAGE-FETCH-SIZE" +>mailmessage_fetch_size</A +></DT +><DT +><A +HREF="#MAILMESSAGE-GET-BODYSTRUCTURE" +>mailmessage_get_bodystructure</A +></DT +><DT +><A +HREF="#MAILMESSAGE-FETCH-SECTION" +>mailmessage_fetch_section</A +></DT +><DT +><A +HREF="#MAILMESSAGE-FETCH-SECTION-HEADER" +>mailmessage_fetch_section_header</A +></DT +><DT +><A +HREF="#MAILMESSAGE-FETCH-SECTION-MIME" +>mailmessage_fetch_section_mime</A +></DT +><DT +><A +HREF="#MAILMESSAGE-FETCH-SECTION-BODY" +>mailmessage_fetch_section_body</A +></DT +><DT +><A +HREF="#MAILMESSAGE-FETCH-ENVELOPE" +>mailmessage_fetch_envelope</A +></DT +><DT +><A +HREF="#MAILMESSAGE-GET-FLAGS" +>mailmessage_get_flags</A +></DT +><DT +><A +HREF="#MAILMESSAGE-RESOLVE-SINGLE-FIELDS" +>mailmessage_resolve_single_fields</A +></DT +><DT +><A +HREF="#MAILMESSAGE-LIST" +>Message list</A +></DT +><DT +><A +HREF="#MAILMESSAGE-TREE" +>Message tree</A +></DT +><DT +><A +HREF="#MAIL-FLAGS" +>Message flags</A +></DT +><DT +><A +HREF="#AEN3467" +>Example</A +></DT +></DL +></DD +><DT +><A +HREF="#AEN3472" +>Session</A +></DT +><DD +><DL +><DT +><A +HREF="#MAILSESSION-DRIVER" +>Session driver</A +></DT +><DT +><A +HREF="#MAILSESSION" +>Session</A +></DT +><DT +><A +HREF="#AEN3670" +>mailsession_parameters</A +></DT +><DT +><A +HREF="#AEN3674" +>mailsession_connect_stream</A +></DT +><DT +><A +HREF="#AEN3678" +>mailsession_connect_path</A +></DT +><DT +><A +HREF="#AEN3682" +>mailsession_starttls</A +></DT +><DT +><A +HREF="#AEN3686" +>mailsession_login</A +></DT +><DT +><A +HREF="#AEN3690" +>mailsession_logout</A +></DT +><DT +><A +HREF="#AEN3694" +>mailsession_noop</A +></DT +><DT +><A +HREF="#AEN3698" +>mailsession_check_folder</A +></DT +><DT +><A +HREF="#AEN3702" +>mailsession_select_folder</A +></DT +><DT +><A +HREF="#AEN3706" +>mailsession_expunge_folder</A +></DT +><DT +><A +HREF="#AEN3710" +>mailsession_status_folder</A +></DT +><DT +><A +HREF="#AEN3714" +>mailsession_messages_number</A +></DT +><DT +><A +HREF="#AEN3718" +>mailsession_recent_number</A +></DT +><DT +><A +HREF="#AEN3722" +>mailsession_unseen_number</A +></DT +><DT +><A +HREF="#AEN3726" +>mailsession_append_message</A +></DT +><DT +><A +HREF="#AEN3730" +>mailsession_get_messages_list</A +></DT +><DT +><A +HREF="#AEN3734" +>mailsession_get_envelopes_list</A +></DT +><DT +><A +HREF="#AEN3741" +>mailsession_get_message</A +></DT +><DT +><A +HREF="#AEN3750" +>mailsession_get_message_by_uid</A +></DT +></DL +></DD +></DL +></DD +></DL +></DIV +><DIV +CLASS="LOT" +><DL +CLASS="LOT" +><DT +><B +>List of Examples</B +></DT +><DT +>2-1. <A +HREF="#AEN35" +>carray creation</A +></DT +><DT +>2-2. <A +HREF="#AEN45" +>preallocating carray</A +></DT +><DT +>2-3. <A +HREF="#AEN66" +>carray access</A +></DT +><DT +>2-4. <A +HREF="#AEN79" +>deletion in carray</A +></DT +><DT +>2-5. <A +HREF="#AEN101" +>clist creation</A +></DT +><DT +>2-6. <A +HREF="#AEN129" +>displaying content of clist</A +></DT +><DT +>2-7. <A +HREF="#AEN145" +>deleting elements in a clist</A +></DT +><DT +>2-8. <A +HREF="#AEN158" +>merging two clists</A +></DT +><DT +>2-9. <A +HREF="#AEN191" +>chash insert and lookup</A +></DT +><DT +>2-10. <A +HREF="#AEN198" +>key deletion in a chash</A +></DT +><DT +>2-11. <A +HREF="#AEN219" +>running through a chash</A +></DT +><DT +>3-1. <A +HREF="#AEN431" +>example of mailbox</A +></DT +><DT +>3-2. <A +HREF="#AEN438" +>mailbox creation and display</A +></DT +><DT +>3-3. <A +HREF="#AEN465" +>address creation and display</A +></DT +><DT +>3-4. <A +HREF="#AEN480" +>Creation and display of mailimf_mailbox_list</A +></DT +><DT +>3-5. <A +HREF="#AEN495" +>creation and display of list of addresses</A +></DT +><DT +>3-6. <A +HREF="#AEN502" +>example of group</A +></DT +><DT +>3-7. <A +HREF="#AEN515" +>creation and display of a group</A +></DT +><DT +>3-8. <A +HREF="#AEN522" +>example of date</A +></DT +><DT +>3-9. <A +HREF="#AEN553" +>creation and display of date</A +></DT +><DT +>3-10. <A +HREF="#AEN569" +>creation and display of Date field</A +></DT +><DT +>3-11. <A +HREF="#AEN585" +>creation and display of a From header</A +></DT +><DT +>3-12. <A +HREF="#AEN601" +>creation and display of Sender field</A +></DT +><DT +>3-13. <A +HREF="#AEN616" +>creation and display of Reply-To field</A +></DT +><DT +>3-14. <A +HREF="#AEN632" +>creation and display of To field</A +></DT +><DT +>3-15. <A +HREF="#AEN648" +>creation and display of Cc field</A +></DT +><DT +>3-16. <A +HREF="#AEN664" +>creation and display of Bcc field</A +></DT +><DT +>3-17. <A +HREF="#AEN673" +>example of Message-ID</A +></DT +><DT +>3-18. <A +HREF="#AEN684" +>creation and display of Message-ID field</A +></DT +><DT +>3-19. <A +HREF="#AEN702" +>creation and display of In-Reply-To field</A +></DT +><DT +>3-20. <A +HREF="#AEN720" +>creation and display of References field</A +></DT +><DT +>3-21. <A +HREF="#AEN734" +>creation and display of Subject field</A +></DT +><DT +>3-22. <A +HREF="#AEN748" +>creation and display of Comment field</A +></DT +><DT +>3-23. <A +HREF="#AEN763" +>creation and display of Keywords field</A +></DT +><DT +>3-24. <A +HREF="#AEN778" +>creation and display of Return-Path field</A +></DT +><DT +>3-25. <A +HREF="#AEN794" +>Creation and display of return path</A +></DT +><DT +>3-26. <A +HREF="#AEN814" +>creation and display of non-standard fields</A +></DT +><DT +>3-27. <A +HREF="#AEN961" +>creation and display of field</A +></DT +><DT +>3-28. <A +HREF="#AEN977" +>creation and display of header fields</A +></DT +><DT +>3-29. <A +HREF="#AEN997" +>creation and display of message body</A +></DT +><DT +>3-30. <A +HREF="#AEN1017" +>creation and display of message</A +></DT +><DT +>3-31. <A +HREF="#AEN1088" +>using mailimf_single_fields</A +></DT +><DT +>3-32. <A +HREF="#AEN1091" +>using mailimf_single_fields without memory allocation</A +></DT +><DT +>3-33. <A +HREF="#AEN1120" +>parsing a list of addresses</A +></DT +><DT +>3-34. <A +HREF="#AEN1147" +>parsing an address</A +></DT +><DT +>3-35. <A +HREF="#AEN1174" +>parsing a message body</A +></DT +><DT +>3-36. <A +HREF="#AEN1201" +>parsing commonly used fields and return other fields + in a non-parsed form</A +></DT +><DT +>3-37. <A +HREF="#AEN1228" +>parsing commonly used fields</A +></DT +><DT +>3-38. <A +HREF="#AEN1255" +>parsing optional fields</A +></DT +><DT +>3-39. <A +HREF="#AEN1282" +>parsing header fields</A +></DT +><DT +>3-40. <A +HREF="#AEN1304" +>skipping fields</A +></DT +><DT +>3-41. <A +HREF="#AEN1329" +>parsing a list of mailboxes</A +></DT +><DT +>3-42. <A +HREF="#AEN1354" +>parsing a mailbox</A +></DT +><DT +>3-43. <A +HREF="#AEN1378" +>parsing a message</A +></DT +><DT +>3-44. <A +HREF="#AEN1411" +>creating a list of mailboxes</A +></DT +><DT +>3-45. <A +HREF="#AEN1553" +>creation of header fields</A +></DT +><DT +>3-46. <A +HREF="#AEN1583" +>rendering of fields</A +></DT +><DT +>4-1. <A +HREF="#AEN1635" +>create and display MIME composite type</A +></DT +><DT +>4-2. <A +HREF="#AEN1667" +>Creation and display of MIME content type</A +></DT +><DT +>4-3. <A +HREF="#AEN1691" +>Creation and display of MIME discrete type</A +></DT +><DT +>4-4. <A +HREF="#AEN1757" +>Creation and display of MIME header field</A +></DT +><DT +>4-5. <A +HREF="#AEN1784" +>Creation and display of MIME transfer encoding mechanism</A +></DT +><DT +>4-6. <A +HREF="#AEN1799" +>Creation and display of MIME fields</A +></DT +><DT +>4-7. <A +HREF="#AEN1821" +>Creation and display of MIME type parameter</A +></DT +><DT +>4-8. <A +HREF="#AEN1851" +>Creation and display of MIME main type</A +></DT +><DT +>4-9. <A +HREF="#AEN1864" +>Creation and display of language of MIME part</A +></DT +><DT +>4-10. <A +HREF="#AEN1906" +>Creation and display of MIME part content</A +></DT +><DT +>4-11. <A +HREF="#AEN2007" +>Creation and display of MIME part</A +></DT +><DT +>4-12. <A +HREF="#AEN2026" +>Creation and display of MIME disposition information</A +></DT +><DT +>4-13. <A +HREF="#AEN2041" +>Creation and display of MIME disposition type</A +></DT +><DT +>4-14. <A +HREF="#AEN2090" +>Creation and display of MIME disposition + parameter</A +></DT +><DT +>4-15. <A +HREF="#AEN2177" +>Creation and display of single fields</A +></DT +><DT +>4-16. <A +HREF="#AEN2203" +>Parsing MIME content type</A +></DT +><DT +>4-17. <A +HREF="#AEN2227" +>Parsing MIME description</A +></DT +><DT +>4-18. <A +HREF="#AEN2251" +>parsing MIME encoding mechanism</A +></DT +><DT +>4-19. <A +HREF="#AEN2267" +>parsing MIME header field</A +></DT +><DT +>4-20. <A +HREF="#AEN2291" +>Parsing MIME content identifier</A +></DT +><DT +>4-21. <A +HREF="#AEN2307" +>parsing MIME header fields</A +></DT +><DT +>4-22. <A +HREF="#AEN2331" +>parsing MIME version</A +></DT +><DT +>4-23. <A +HREF="#AEN2356" +>parsing a MIME parameter</A +></DT +><DT +>4-24. <A +HREF="#AEN2380" +>Parsing the MIME content langage</A +></DT +><DT +>4-25. <A +HREF="#AEN2404" +>Parsing the MIME content disposition</A +></DT +><DT +>4-26. <A +HREF="#AEN2427" +>parsing a MIME content disposition type</A +></DT +><DT +>4-27. <A +HREF="#AEN2455" +>decoding a MIME encoded header string</A +></DT +><DT +>4-28. <A +HREF="#AEN2478" +>parsing a MIME message</A +></DT +><DT +>4-29. <A +HREF="#AEN2501" +>Parsing a base64 encoded part</A +></DT +><DT +>4-30. <A +HREF="#AEN2524" +>Parsing a quoted printable encoded part</A +></DT +><DT +>4-31. <A +HREF="#AEN2547" +>Parsing a binary encoded part</A +></DT +><DT +>4-32. <A +HREF="#AEN2580" +>Parsing a MIME encoded part</A +></DT +><DT +>4-33. <A +HREF="#AEN2610" +>rendering MIME header fields</A +></DT +><DT +>4-34. <A +HREF="#AEN2649" +>render base64 or quoted printable</A +></DT +><DT +>4-35. <A +HREF="#AEN2694" +>creating a MIME content disposition</A +></DT +><DT +>4-36. <A +HREF="#AEN2713" +>creating a MIME header fields list</A +></DT +><DT +>4-37. <A +HREF="#AEN2728" +>creating new fields</A +></DT +><DT +>4-38. <A +HREF="#AEN2746" +>Creating a MIME content type</A +></DT +><DT +>4-39. <A +HREF="#AEN2779" +>creating MIME content</A +></DT +><DT +>4-40. <A +HREF="#AEN2809" +>creating a MIME part</A +></DT +><DT +>4-41. <A +HREF="#AEN2837" +>setting preamble and epilogue</A +></DT +><DT +>4-42. <A +HREF="#AEN2861" +>creating a MIME part</A +></DT +><DT +>4-43. <A +HREF="#AEN2892" +>modifying MIME structure</A +></DT +><DT +>4-44. <A +HREF="#AEN2909" +>modifying MIME structure</A +></DT +><DT +>4-45. <A +HREF="#AEN2943" +>creating MIME fields with only Content-Transfer-Encoding</A +></DT +><DT +>4-46. <A +HREF="#AEN2960" +>extracting MIME encoding mechanism</A +></DT +><DT +>4-47. <A +HREF="#AEN2985" +>extracting information from MIME content type</A +></DT +><DT +>5-1. <A +HREF="#AEN3079" +>use of storage</A +></DT +><DT +>5-2. <A +HREF="#AEN3195" +>use of folder</A +></DT +><DT +>5-3. <A +HREF="#AEN3469" +>use of message</A +></DT +></DL +></DIV +><DIV +CLASS="CHAPTER" +><HR><H1 +><A +NAME="AEN13" +></A +>Chapter 1. Introduction</H1 +><P +> This document will describe the API of libEtPan! + </P +></DIV +><DIV +CLASS="CHAPTER" +><HR><H1 +><A +NAME="AEN16" +></A +>Chapter 2. Tools and datatypes</H1 +><P +> libEtPan! include a collection of datatypes such as lists, + arrays, hash tables and tools such as buffered I/O. + </P +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN19" +>Array</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +typedef struct carray_s carray; + </PRE +><P +> <B +CLASS="COMMAND" +>carray</B +> is an array of pointers that will + resize automatically in case a new element is added. + </P +><P +> + The <B +CLASS="COMMAND" +>carray</B +> is implemented with an array + <B +CLASS="COMMAND" +>(void **)</B +> that can be resized. An array has a + size: this is the number of elements that can be added before + the table is resized. It also has a count of elements: this is + the elements that exist in the array. + </P +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CARRAY-NEW" +>carray_new and carray_free</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>carray * carray_new(unsigned int initsize); + +void carray_free(carray * array); + </PRE +><P +> <B +CLASS="COMMAND" +>carray_new()</B +> creates a new array with an + initial size. The array is not resized until the number of + element reach the initial size. It returns + <B +CLASS="COMMAND" +>NULL</B +> in case of failure. + </P +><P +> <B +CLASS="COMMAND" +>carray_free()</B +> releases memory used by the + given array. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN35" +></A +><P +><B +>Example 2-1. carray creation</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <stdlib.h> + +#define SIZE 50 + +int main(void) +{ + carray * a; + + a = carray_new(SIZE); + if (a == NULL) + exit(EXIT_FAILURE); + + /* do things here */ + + carray_free(a); + + exit(EXIT_SUCESS); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CARRAY-SET-SIZE" +>carray_set_size</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int carray_set_size(carray * array, uint32_t new_size); + </PRE +><P +> <B +CLASS="COMMAND" +>carray_set_size()</B +> sets the size of the + array. It returns <B +CLASS="COMMAND" +>0</B +> in case of success, + <B +CLASS="COMMAND" +>-1</B +> in case of failure. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN45" +></A +><P +><B +>Example 2-2. preallocating carray</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <stdlib.h> + +#define SIZE 50 +#define NEWSIZE 200 + +int main(void) +{ + carray * a; + unsigned int i; + char p[500]; + + a = carray_new(SIZE); + if (a == NULL) + goto err; + + r = carray_set_size(NEWSIZE); + if (r < 0) + goto free; + + for(i = 0 ; i < NEWSIZE ; i ++) + carray_set(a, i, &p[i]); + + /* do things here */ + + carray_free(a); + + exit(EXIT_SUCESS); + + free: + carray_free(a); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CARRAY-COUNT" +>carray_count, carray_add, carray_get and carray_set</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int carray_count(carray); + +int carray_add(carray * array, void * data, unsigned int * index); + +void * carray_get(carray * array, unsigned int indx); + +void carray_set(carray * array, unsigned int indx, void * value); + </PRE +><P +> <B +CLASS="COMMAND" +>carray_count()</B +> returns the number of + elements in the <B +CLASS="COMMAND" +>carray</B +>. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>carray_add()</B +>adds an element at the end of + the array. The <B +CLASS="COMMAND" +>index</B +> of the element is + returns in <B +CLASS="COMMAND" +>(* index)</B +> if + <B +CLASS="COMMAND" +>index</B +> is not <B +CLASS="COMMAND" +>NULL</B +>. It + returns <B +CLASS="COMMAND" +>0</B +> in case of success, + <B +CLASS="COMMAND" +>-1</B +> in case of failure. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>carray_get()</B +> returns the elements contained + at the given cell of the table. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>carray_set()</B +> replace the element at the + given index of table table with the given value. + Complexity is O(1). + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN66" +></A +><P +><B +>Example 2-3. carray access</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <string.h> + +#define SIZE 50 + +int main(void) +{ + carray * a; + int r; + + a = carray_new(SIZE); + if (a == NULL) + goto err; + + r = carray_add(a, "foo-bar-1", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-2", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-3", NULL); + if (r < 0) + goto free; + + for(i = 0 ; i < carray_count(a) ; i ++) { + char * str; + + str = carray_get(a, i); + if (strcmp("foo-bar-2", str) == 0) + carray_set(a, i, "foo-bar-2-replacement"); + + printf("%s\n", str); + } + + carray_free(a); + + exit(EXIT_SUCESS); + + free: + carray_free(a); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CARRAY-DELETE" +>carray_delete</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int carray_delete(carray * array, uint32_t indx); + +int carray_delete_slow(carray * array, uint32_t indx); + +int carray_delete_fast(carray * array, uint32_t indx); + </PRE +><P +> <B +CLASS="COMMAND" +>carray_delete()</B +> removes an element of the + table. Order will not be garanteed. The returned result can + be ignored. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>carray_delete_slow()</B +> removes an element of + the table. Order will be garanteed. The returned result can + be ignored. + Complexity is O(n). + </P +><P +> <B +CLASS="COMMAND" +>carray_delete_fast()</B +> the element will just + be replaced with <B +CLASS="COMMAND" +>NULL</B +>. Order will be kept + but the number of elements will remains the same. The + returned result can be ignored. + Complexity is O(1). + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN79" +></A +><P +><B +>Example 2-4. deletion in carray</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define SIZE 50 + +carray * build_array(void) +{ + carray * a; + + a = carray_new(SIZE); + if (a == NULL) + goto err; + + r = carray_add(a, "foo-bar-1", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-2", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-3", NULL); + if (r < 0) + goto free; + + return a; + + free: + carray_free(a); + err: + exit(EXIT_FAILURE); +} + +void delete(carray * a) +{ + /* deleting foo-bar-1 */ + carray_delete(a, 0); + /* resulting size is 2, order of elements is undefined */ +} + +void delete_slow(carray * a) +{ + /* deleting foo-bar-1 */ + carray_delete_slow(a, 0); + /* resulting size is 2, order of elements is the same */ +} + +void delete_fast(carray * a) +{ + /* deleting foo-bar-1 */ + carray_delete_slow(a, 0); + /* + resulting size is 3, + order of elements is { NULL, foo-bar-2, foo-bar-3 } + */ +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CARRAY-DATA" +>carray_data</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>void ** carray_data(carray); + </PRE +><P +> <B +CLASS="COMMAND" +>carray_data</B +>returns the table used for + implementation : + <B +CLASS="COMMAND" +>(void **)</B +>. + </P +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="CLIST" +>List</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +typedef struct clist_s clist; + +typedef clistcell clistiter; + </PRE +><P +> <B +CLASS="COMMAND" +>clist()</B +> is a list of cells. + Each cell of the list contains one element. This element is a + pointer. An iterator (<B +CLASS="COMMAND" +>clistiter</B +>) is a + pointer to an element of the list. With an iterator, we can + get the previous element of the list, the next element of the + list and the content of the element. + </P +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CLIST-NEW" +>clist_new and clist_free</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>clist * clist_new(void); + +void clist_free(clist *); + </PRE +><P +> <B +CLASS="COMMAND" +>clist_new()</B +> allocates a new empty list and + returns it. + </P +><P +> <B +CLASS="COMMAND" +>clist_free()</B +> frees the entire list with + its cells. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN101" +></A +><P +><B +>Example 2-5. clist creation</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + goto err; + + r = clist_append(list, "foo-bar"); + if (r < 0) + + clist_free(list); + + exit(EXIT_SUCCESS); + + free: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CLIST-COUNT" +>clist_isempty and clist_count</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int clist_isempty(clist *); + +int clist_count(clist *); + </PRE +><P +> <B +CLASS="COMMAND" +>clist_isempty()</B +> returns 1 if the list is + empty, else it is 0. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_count()</B +> returns the number of + elements in the list. + Complexity is O(1). + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CLIST-BEGIN" +>running through clist</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>clistiter * clist_begin(clist *); + +clistiter * clist_end(clist *); + +clistiter * clist_next(clistiter *); + +clistiter * clist_previous(clistiter *); + +void * clist_content(clistiter *); + +void * clist_nth_data(clist * lst, int index); + +clistiter * clist_nth(clist * lst, int index); + </PRE +><P +> <B +CLASS="COMMAND" +>clist_begin()</B +> returns an iterator to the + first element of the list. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_end()</B +> returns an iterator to the last + element of the list. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_next()</B +> returns an iterator to the + next element of the list. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_previous()</B +> returns an iterator to the + previous element of the list. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_content()</B +> returns the element + contained in the cell pointed by the iterator in the list. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_nth()</B +> returns an iterator on the + <B +CLASS="COMMAND" +>index</B +>-th element of the list. + Complexity is O(n). + </P +><P +> <B +CLASS="COMMAND" +>clist_nth_data()</B +> returns the index-th + element of the list. + Complexity is O(n). + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN129" +></A +><P +><B +>Example 2-6. displaying content of clist</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(void) +{ + clist * list; + clistiter * iter; + + list = build_string_list(); + if (list == NULL) + goto err; + + for(iter = clist_begin(list) ; iter != NULL ; iter = + clist_next(iter)) { + char * str; + + str = clist_content(iter); + printf("%s\n", str); + } + + clist_free(list); + + exit(EXIT_SUCCESS); + + free: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CLIST-APPEND" +>clist modification</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int clist_prepend(clist *, void *); + +int clist_append(clist *, void *); + +int clist_insert_before(clist *, clistiter *, void *); + +int clist_insert_after(clist *, clistiter *, void *); + +clistiter * clist_delete(clist *, clistiter *); + </PRE +><P +> <B +CLASS="COMMAND" +>clist_prepend()</B +> adds an element at the + beginning of the list. Returns 0 on sucess, -1 on error. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_append()</B +> adds an element at the end + of the list. Returns 0 on sucess, -1 on error. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_insert_before()</B +> adds an element + before the element pointed by the given iterator in the + list. Returns 0 on sucess, -1 on error. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_insert_after()</B +> adds an element after + the element pointed by the given iterator in the list. + Returns 0 on sucess, -1 on error. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_delete()</B +> the elements pointed by + the given iterator in the list and returns an iterator to + the next element of the list. + Complexity is O(1). + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN145" +></A +><P +><B +>Example 2-7. deleting elements in a clist</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +voir print_content(void * content, void * user_data) +{ + char * str; + + str = content; + + printf("%s\n", str); +} + +int main(void) +{ + clist * list; + clistiter * iter; + + list = build_string_list(); + if (list == NULL) + goto err; + + iter = = clist_begin(list); + while (iter != NULL) + char * str; + + str = clist_content(iter); + if (strcmp(str, "foo-bar") == 0) + iter = clist_delete(list, cur); + else + iter = clist_next(iter); + } + + clist_foreach(list, print_content, NULL); + printf("\n"); + + clist_free(list); + + exit(EXIT_SUCCESS); + + free: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CLIST-FOREACH" +>clist_foreach</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>typedef void (* clist_func)(void *, void *); + +void clist_foreach(clist * lst, clist_func func, void * data); + </PRE +><P +> <B +CLASS="COMMAND" +>clist_foreach()</B +> apply a fonction to each + element of the list. + Complexity is O(n). + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CLIST-CONCAT" +>clist_concat</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>void clist_concat(clist * dest, clist * src); + </PRE +><P +> <B +CLASS="COMMAND" +>clist_concat()</B +> adds all the elements of src + at the end of dest. Elements are added in the same + order. src is an empty list when the operation is finished. + Complexity is O(1). + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN158" +></A +><P +><B +>Example 2-8. merging two clists</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(void) +{ + clist * list; + clist * list_2; + clistiter * iter; + + list = build_string_list(); + if (list == NULL) + goto err; + + list_2 = build_string_list_2(); + if (list == NULL) + goto free_list; + + clist_concat(list, list_2); + clist_free(list_2); + + for(iter = clist_begin(list) ; iter != NULL ; iter = + clist_next(iter)) { + char * str; + + str = clist_content(iter); + printf("%s\n", str); + } + + clist_free(list); + + exit(EXIT_SUCCESS); + + free_list: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN161" +>Hash table</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +typedef struct chash chash; + +typedef struct chashcell chashiter; + +typedef struct { + char * data; + int len; +} chashdatum; + </PRE +><P +> + <B +CLASS="COMMAND" +>chash</B +> is a hash table. + <B +CLASS="COMMAND" +>chashiter</B +> is a pointer to an element of the + hash table. + <B +CLASS="COMMAND" +>chashdatum</B +> is an element to be placed in + the hash table as a key or a value. It consists in + data and a corresponding length. + </P +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CHASH-NEW" +>chash_new and chash_free</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#define CHASH_COPYNONE 0 +#define CHASH_COPYKEY 1 +#define CHASH_COPYVALUE 2 +#define CHASH_COPYALL (CHASH_COPYKEY | CHASH_COPYVALUE) + +chash * chash_new(int size, int flags); + +void chash_free(chash * hash); + </PRE +><P +> <B +CLASS="COMMAND" +>chash_new()</B +> returns a new empty hash table + or <B +CLASS="COMMAND" +>NULL</B +> if this + failed. <B +CLASS="COMMAND" +>size</B +> is the initial size of the + table used for implementation. <B +CLASS="COMMAND" +>flags</B +> can + be a combinaison of <B +CLASS="COMMAND" +>CHASH_COPYKEY</B +> and + <B +CLASS="COMMAND" +>CHASH_COPYVALUE</B +>. + <B +CLASS="COMMAND" +>CHASH_COPYKEY</B +> enables copy of key, so + that the initial value used for <B +CLASS="COMMAND" +>chash_set()</B +> + </P +><P +> <B +CLASS="COMMAND" +>chash_free()</B +> releases memory used by the + hash table. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CHASH-GET" +>chash_set and chash_get</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int chash_set(chash * hash, + chashdatum * key, chashdatum * value, chashdatum * oldvalue); + +int chash_get(chash * hash, + chashdatum * key, chashdatum * result); + </PRE +><P +> <B +CLASS="COMMAND" +>chash_set()</B +> adds a new element into the + hash table. If a previous element had the same key, it is + returns into oldvalue if <B +CLASS="COMMAND" +>oldvalue</B +> is + different of NULL. + Medium complexity is O(1). + </P +><P +> returns -1 if it fails, 0 on success. + </P +><P +> <B +CLASS="COMMAND" +>chash_get()</B +>returns the corresponding value + of the given key. If there is no corresponding value, -1 is + returned. 0 on success. + Medium complexity is O(1). + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN191" +></A +><P +><B +>Example 2-9. chash insert and lookup</B +></P +><PRE +CLASS="PROGRAMLISTING" +>int main(void) +{ + chash * hash; + int r; + chashdatum key; + chashdatum value; + char * str1 = "my-data"; + char * str2 = "my-data"; + + hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE); + + key.data = "foo"; + key.len = strlen("foo"); + value.data = str1; + value.data = strlen(str1) + 1; + /* + 1 is needed to get the terminal zero in the returned string */ + r = chash_set(hash, &key, &value, NULL); + if (r < 0) + goto free_hash; + + key.data = "bar"; + key.len = strlen("bar"); + value.data = str2; + value.data = strlen(str2) + 1; + if (r < 0) + goto free_hash; + + key.data = "foo"; + key.len = strlen("foo"); + r = chash_get(hash, &key, &value); + if (r < 0) { + printf("element not found\n"); + } + else { + char * str; + + str = value.data; + printf("found : %s", str); + } + + chash_free(hash); + + exit(EXIT_SUCCESS); + + free_hash: + chash_free(hash); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CHASH-DELETE" +>chash_delete</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int chash_delete(chash * hash, + chashdatum * key, chashdatum * oldvalue); + </PRE +><P +> deletes the key/value pair given the corresponding key. + The value is returned in old_value. + If there is no corresponding value, -1 is returned. 0 on success. + Medium complexity is O(1). + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN198" +></A +><P +><B +>Example 2-10. key deletion in a chash</B +></P +><PRE +CLASS="PROGRAMLISTING" +>int main(void) +{ + chash * hash; + int r; + chashdatum key; + chashdatum value; + char * str1 = "my-data"; + char * str2 = "my-data"; + + hash = build_hash(); + + key.data = "foo"; + key.len = strlen("foo"); + chash_delete(hash, &key, &value); + + /* it will never be possible to lookup "foo" */ + key.data = "foo"; + key.len = strlen("foo"); + r = chash_get(hash, &key, &value); + if (r < 0) { + printf("element not found\n"); + } + else { + char * str; + + str = value.data; + printf("found : %s", str); + } + + chash_free(hash); + + exit(EXIT_SUCCESS); + + free_hash: + chash_free(hash); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CHASH-RESIZE" +>chash_resize</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int chash_resize(chash * hash, int size); + </PRE +><P +> <B +CLASS="COMMAND" +>chash_resize()</B +> changes the size of the + table used for implementation of the hash table. + returns 0 on success, -1 on failure. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CHASH-BEGIN" +>running through the chash</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>chashiter * chash_begin(chash * hash); + +chashiter * chash_next(chash * hash, chashiter * iter); + +void chash_key(chashiter * iter, chashdatum * result); + +void chash_value(chashiter iter, chashdatum * result); + </PRE +><P +> <B +CLASS="COMMAND" +>chash_begin()</B +> returns a pointer to the + first element of the hash table. Returns + <B +CLASS="COMMAND" +>NULL</B +> if there is no elements in the hash + table. + Complexity is O(n). + </P +><P +> <B +CLASS="COMMAND" +>chash_next()</B +> returns a pointer to the next + element of the hash table. Returns <B +CLASS="COMMAND" +>NULL</B +> + if there is no next element. + Complexity is O(n) but n calls to chash_next() also has + a complexity of O(n). + </P +><P +> <B +CLASS="COMMAND" +>chash_key()</B +> returns the key of the given + element of the hash table. + </P +><P +> <B +CLASS="COMMAND" +>chash_value</B +> returns the value of the + given element of the hash table. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN219" +></A +><P +><B +>Example 2-11. running through a chash</B +></P +><PRE +CLASS="PROGRAMLISTING" +>int main(void) +{ + chash * hash; + int r; + chashiter * iter; + + hash = build_hash(); + + /* this will display all the values stored in the hash */ + for(iter = chash_begin(hash) ; iter != NULL ; iter = + chash_next(hash, iter)) { + chashdatum key; + chashdatum value; + char * str; + + chash_value(iter, &value); + str = value.data; + printf("%s\n", str); + } + + chash_free(hash); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CHASH-COUNT" +>chash_size and chash_count</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int chash_size(chash * hash); + +int chash_count(chash * hash); + </PRE +><P +> <B +CLASS="COMMAND" +>chash_size()</B +> returns the size of the table + used for implementation of the hash table. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>chash_count()</B +> returns the number of + elements in the hash table. + Complexity is O(1). + </P +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN229" +>Buffered I/O</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +> +#include <libetpan/libetpan.h> + +typedef struct _mailstream mailstream; + </PRE +><P +> streams are objects where we can read data from and write data + to. They are not seekable. That can be for example a pipe or a + network stream. + </P +><PRE +CLASS="PROGRAMLISTING" +>mailstream * mailstream_new(mailstream_low * low, size_t buffer_size); + +int mailstream_close(mailstream * s); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstream_new()</B +> creates a new stream + stream with the low-level (see <A +HREF="#MAILSTREAM-LOW" +>the Section called <I +>non-buffered I/O</I +></A +>) + stream and a given buffer size. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_close()</B +> closes the stream. + This function will be in charge to free the + <B +CLASS="COMMAND" +>mailstream_low</B +> structure. + </P +><PRE +CLASS="PROGRAMLISTING" +> +ssize_t mailstream_write(mailstream * s, void * buf, size_t count); + +int mailstream_flush(mailstream * s); + +ssize_t mailstream_read(mailstream * s, void * buf, size_t count); + +ssize_t mailstream_feed_read_buffer(mailstream * s); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstream_write()</B +> writes a buffer to the + given stream. This write operation will be buffered. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_flush()</B +> will force a write of + all buffered data for a given stream. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_read()</B +> reads data from the + stream to the given buffer. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_feed_read_buffer()</B +> this function + will just fill the buffer for reading. + </P +><PRE +CLASS="PROGRAMLISTING" +> +mailstream_low * mailstream_get_low(mailstream * s); + +void mailstream_set_low(mailstream * s, mailstream_low * low); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstream_get_low()</B +> returns the low-level + stream of the given stream. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_set_low()</B +> changes the low-level + of the given stream. Useful, for + example, when a stream change from clear stream to SSL + stream. + </P +><PRE +CLASS="PROGRAMLISTING" +>char * mailstream_read_line(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_append(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line); + +char * mailstream_read_multiline(mailstream * s, size_t size, + MMAPString * stream_buffer, + MMAPString * multiline_buffer, + size_t progr_rate, + progress_function * progr_fun); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstream_read_line()</B +> reads an entire line + from the buffer and store it into the + given string. returns <B +CLASS="COMMAND" +>NULL</B +> on error, the + corresponding array + of <B +CLASS="COMMAND" +>char</B +> is returned otherwise. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_read_line_append()</B +> reads an entire + line from the buffer and appends it to the + given string. returns <B +CLASS="COMMAND" +>NULL</B +> on error, the + array of char corresponding to the entire buffer is returned + otherwise. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_read_line_remove_eol()</B +> reads an + entire line from the buffer and store it into the + given string. All CR LF are removed. + returns <B +CLASS="COMMAND" +>NULL</B +> on error, the corresponding + array of <B +CLASS="COMMAND" +>char</B +> is returned otherwise. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_read_multiline()</B +> reads a + multiline data (several lines, the data are ended with + a single period '.') + from the given stream and store it into the given + multiline buffer (multiline_buffer). progr_rate should be 0 + and progr_fun <B +CLASS="COMMAND" +>NULL</B +> (deprecated things). + <B +CLASS="COMMAND" +>stream_buffer</B +> is a buffer used for internal + work of the function. + size should be 0 (deprecated things). + </P +><PRE +CLASS="PROGRAMLISTING" +> +int mailstream_is_end_multiline(char * line); + </PRE +><P +> returns 1 if the line is an end of multiline data (a single + period '.', eventually with CR and/or LF). 0 is returned + otherwise. + </P +><PRE +CLASS="PROGRAMLISTING" +> +int mailstream_send_data(mailstream * s, char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun); + </PRE +><P +> sends multiline data to the given stream. + <B +CLASS="COMMAND" +>size</B +> is the size of the data. + <B +CLASS="COMMAND" +>progr_rate</B +> and <B +CLASS="COMMAND" +>progr_fun</B +> + are deprecated. <B +CLASS="COMMAND" +>progr_rate</B +> must be 0, + <B +CLASS="COMMAND" +>progr_fun</B +> must be NULL. + </P +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILSTREAM-SOCKET" +>socket stream</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>mailstream * mailstream_socket_open(int fd); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstream_socket_open()</B +> will open a + clear-text socket. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILSTREAM-SSL" +>TLS stream</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>mailstream * mailstream_ssl_open(int fd); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstream_ssl_open()</B +> will open a + TLS/SSL socket. + </P +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="MAILSTREAM-LOW" +>non-buffered I/O</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +> +#include <libetpan/libetpan.h> + +struct mailstream_low_driver { + ssize_t (* mailstream_read)(mailstream_low *, void *, size_t); + ssize_t (* mailstream_write)(mailstream_low *, void *, size_t); + int (* mailstream_close)(mailstream_low *); + int (* mailstream_get_fd)(mailstream_low *); + void (* mailstream_free)(mailstream_low *); +}; + +typedef struct mailstream_low_driver mailstream_low_driver; + +struct _mailstream_low { + void * data; + mailstream_low_driver * driver; +}; + </PRE +><P +> <B +CLASS="COMMAND" +>mailstream_low</B +> is a non-buffered stream. + </P +><P +> The <B +CLASS="COMMAND" +>mailstream_low_driver</B +> is a set of + functions used to access the stream. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>mailstream_read/write/close()</B +> is the same + interface as <B +CLASS="COMMAND" +>read/write/close()</B +> + system calls, except that the file descriptor is replaced with the + <B +CLASS="COMMAND" +>mailstream_low</B +> structure. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mailstream_get_fd()</B +> returns the file + descriptor used for this non-buffered stream. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mailstream_free()</B +> is in charge to free + the internal structure of the mailstream_low and the + mailstream_low itself. + </P +></LI +></UL +><PRE +CLASS="PROGRAMLISTING" +> +mailstream_low * mailstream_low_new(void * data, + mailstream_low_driver * driver); + </PRE +><P +> mailstream_low_new() creates a low-level mailstream with the + given internal structure (data) and using the given set of + functions (driver). + </P +><PRE +CLASS="PROGRAMLISTING" +> +ssize_t mailstream_low_write(mailstream_low * s, void * buf, size_t count); + +ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count); + +int mailstream_low_close(mailstream_low * s); + +int mailstream_low_get_fd(mailstream_low * s); + +void mailstream_low_free(mailstream_low * s); + </PRE +><P +> Each of these calls will call the corresponding function defined + in the driver. + </P +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN312" +>strings</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +> +#include <libetpan/libetpan.h> + +struct _MMAPString +{ + char * str; + size_t len; + size_t allocated_len; + int fd; + size_t mmapped_size; +}; + +typedef struct _MMAPString MMAPString; + </PRE +><P +> MMAPString is a string which size that can increase automatically. + </P +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MMAP-STRING-NEW" +>constructor and destructor</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>MMAPString * mmap_string_new(const char * init); + +MMAPString * mmap_string_new_len(const char * init, size_t len); + +MMAPString * mmap_string_sized_new(size_t dfl_size); + +void mmap_string_free(MMAPString * string); + </PRE +><P +> <B +CLASS="COMMAND" +>mmap_string_new()</B +> allocates a new + string. init is the intial value of the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_new_len()</B +> allocates a new + string. init is the intial value of the + string, len is the length of the initial string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_sized_new()</B +> allocates a new + string. dfl_size is the initial allocation of + the string. <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_free()</B +> release the memory used + by the string. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MMAP-STRING-ASSIGN" +>string value modification</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>MMAPString * mmap_string_assign(MMAPString * string, const char * rval); + +MMAPString * mmap_string_truncate(MMAPString *string, size_t len); + </PRE +><P +> <B +CLASS="COMMAND" +>mmap_string_assign()</B +> sets a new value for + the given string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_truncate()</B +> sets a length for + the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + </P +><PRE +CLASS="PROGRAMLISTING" +>MMAPString * mmap_string_set_size (MMAPString * string, size_t len); + </PRE +><P +> sets the allocation of the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MMAP-STRING-APPEND" +>insertion in string, deletion in string</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>MMAPString * mmap_string_insert_len(MMAPString * string, size_t pos, + const char * val, size_t len); + +MMAPString * mmap_string_append(MMAPString * string, const char * val); + +MMAPString * mmap_string_append_len(MMAPString * string, + const char * val, size_t len); + +MMAPString * mmap_string_append_c(MMAPString * string, char c); + +MMAPString * mmap_string_prepend(MMAPString * string, const char * val); + +MMAPString * mmap_string_prepend_c(MMAPString * string, char c); + +MMAPString * mmap_string_prepend_len(MMAPString * string, const char * val, + size_t len); + +MMAPString * mmap_string_insert(MMAPString * string, size_t pos, + const char * val); + +MMAPString * mmap_string_insert_c(MMAPString *string, size_t pos, + char c); + +MMAPString * mmap_string_erase(MMAPString * string, size_t pos, + size_t len); + </PRE +><P +> For complexity here, n is the size of the given MMAPString, + and len is the size of the string to insert. + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_insert_len()</B +> inserts the given + string value of given length in the string at the given + position. <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(n + len). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_append()</B +> appends the given + string value at the end of the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(len). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_append_len()</B +> appends the + given string value of given length at the end of the + string. <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(len). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_append_c()</B +> appends the given + character at the end of the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_prepend()</B +> insert the given + string value at the beginning of the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(n + len). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_prepend_c()</B +> insert the given + character at the beginning of the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(n). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_prepend_len()</B +> insert the given + string value of given length at the beginning of the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(n + len). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_insert()</B +> inserts the given + string value in the string at the given position. + NULL will be returned on error. + Complexity is O(n + len). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_insert_c()</B +> inserts the given + character in the string at the given position. + NULL will be returned on error. + Complexity is O(n). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_erase()</B +> removes the given + count of characters (len) at the given position of the + string. <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(n). + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MMAP-STRING-REF" +>referencing string</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int mmap_string_ref(MMAPString * string); + +int mmap_string_unref(char * str); + </PRE +><P +> MMAPString provides a mechanism that let you use MMAPString + like normal strings. You have first to use + <B +CLASS="COMMAND" +>mmap_string_ref()</B +>, so that you notify + that the string will be used as a normal string, then, you + use <B +CLASS="COMMAND" +>mmapstr->str</B +> to refer to the + string. When you have finished and you want to free a string + corresponding to a <B +CLASS="COMMAND" +>MMAPString</B +>, you will + use <B +CLASS="COMMAND" +>mmap_string_unref</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_ref()</B +> references the string + so that the array of characters can be used as a normal + string then released with + <B +CLASS="COMMAND" +>mmap_string_unref()</B +>. + The array of characters will be obtained with string->str. + returns -1 on error, 0 on success. + </P +></DIV +></DIV +></DIV +><DIV +CLASS="CHAPTER" +><HR><H1 +><A +NAME="IMF" +></A +>Chapter 3. Internet Message Format</H1 +><P +> libEtPan! implements Internet Message parser. Currently, format + is RFC 2822. + This module also allows to generate messages. + </P +><DIV +CLASS="WARNING" +><P +></P +><TABLE +CLASS="WARNING" +BORDER="1" +WIDTH="100%" +><TR +><TD +ALIGN="CENTER" +><B +>Warning</B +></TD +></TR +><TR +><TD +ALIGN="LEFT" +><P +> All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + </P +><P +> allocation functions will return <B +CLASS="COMMAND" +>NULL</B +> on failure + + functions returning integer will be returning one of the + following error code: + <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +>, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_PARSE</B +>, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_MEMORY</B +>, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_INVAL</B +>, + or <B +CLASS="COMMAND" +>MAILIMF_ERROR_FILE</B +>. + </P +></TD +></TR +></TABLE +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN397" +>Quick start</A +></H2 +><P +> You will need this module when you want to parse headers + of messages or when you want to build message headers + conformant to standards. + </P +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN400" +>Parse message headers</A +></H3 +><P +> You will use one of the four following functions, depending + on your needs : + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>mailimf_envelope_and_optional_fields_parse</B +> + (<A +HREF="#MAILIMF-ENVELOPE-AND-OPTIONAL-FIELDS-PARSE" +>the Section called <I +>mailimf_envelope_and_optional_fields_parse</I +></A +>), + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mailimf_envelope_fields_parse</B +> + (<A +HREF="#MAILIMF-ENVELOPE-FIELDS-PARSE" +>the Section called <I +>mailimf_envelope_fields_parse</I +></A +>), + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mailimf_optional_fields_parse</B +> + (<A +HREF="#MAILIMF-OPTIONAL-FIELDS-PARSE" +>the Section called <I +>mailimf_optional_fields_parse</I +></A +>), + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mailimf_fields_parse</B +> + (<A +HREF="#MAILIMF-FIELDS-PARSE" +>the Section called <I +>mailimf_fields_parse</I +></A +>). + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN420" +>Render the message headers</A +></H3 +><P +> Build your message headers, then use + <B +CLASS="COMMAND" +>mailimf_fields_write</B +> + (<A +HREF="#MAILIMF-FIELDS-WRITE" +>the Section called <I +>Header fields</I +></A +>) + to render the headers. + </P +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN425" +>Data types</A +></H2 +><DIV +CLASS="SECT2" +><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-MAILBOX" +>mailimf_mailbox - mailbox</A +></H3 +><P +>#include <libetpan/libetpan.h> + +struct mailimf_mailbox { + char * mb_display_name; /* can be NULL */ + char * mb_addr_spec; /* != NULL */ +}; + +struct mailimf_mailbox * +mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec); + +void mailimf_mailbox_free(struct mailimf_mailbox * mailbox); + </P +><P +> This is an email mailbox with a display name. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN431" +></A +><P +><B +>Example 3-1. example of mailbox</B +></P +><PRE +CLASS="PROGRAMLISTING" +>DINH Viet Hoa <hoa@users.sourceforge.net> + </PRE +></DIV +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_new</B +> creates and + initializes a data structure with a value. + Strings given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_free</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN438" +></A +><P +><B +>Example 3-2. mailbox creation and display</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_mailbox * mb; + char * display_name; + char * address; + + display_name = strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="); + address = strdup("dinh.viet.hoa@free.fr"); + mb = mailimf_mailbox_new(str, address); + /* do the things */ + mailimf_mailbox_free(mb); + + return 0; +} + +/* display mailbox information */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_mailbox(struct mailimf_mailbox * mb) +{ + if (mb->mb_display_name != NULL) + printf("display name: %s\n", mb->mb_display_name); + printf("address specifier : %s\n", mb->mb_addr_spec); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-ADDRESS" +>mailimf_address - address</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_address { + int ad_type; + union { + struct mailimf_mailbox * ad_mailbox; /* can be NULL */ + struct mailimf_group * ad_group; /* can be NULL */ + } ad_data; +}; + +struct mailimf_address * +mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox, + struct mailimf_group * ad_group); + +void mailimf_address_free(struct mailimf_address * address); + </PRE +><P +> This is a mailbox or a group of mailbox. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>ad_type</B +> can be MAILIMF_ADDRESS_MAILBOX or + <B +CLASS="COMMAND" +>MAILIMF_ADDRESS_GROUP</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>ad_data.ad_mailbox</B +> is a mailbox if + <B +CLASS="COMMAND" +>ad_type</B +> is + <B +CLASS="COMMAND" +>MAILIMF_ADDRESS_MAILBOX</B +> + see <A +HREF="#MAILIMF-MAILBOX" +>the Section called <I +>mailimf_mailbox - mailbox</I +></A +>) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>ad_data.group</B +> is a group if type is + <B +CLASS="COMMAND" +>MAILIMF_ADDRESS_GROUP</B +>. + see <A +HREF="#MAILIMF-GROUP" +>the Section called <I +>mailimf_group - named group of mailboxes</I +></A +>) + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_address_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_address_free</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN465" +></A +><P +><B +>Example 3-3. address creation and display</B +></P +><PRE +CLASS="PROGRAMLISTING" +>/* creates an address of type mailbox */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_address * a_mb; + struct mailimf_mailbox * mb; + char * display_name; + char * address; + + display_name = strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="); + address = strdup("dinh.viet.hoa@free.fr"); + mb = mailimf_mailbox_new(str, address); + + a_mb = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + /* do the things */ + mailimf_address_free(a_mb); +} + +/* creates an address of type group */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_address * a_g; + struct mailimf_group * g; + char * display_name; + + display_name = strdup("undisclosed-recipient"); + g = mailimf_group_new(display_name, NULL); + + a_g = mailimf_address_new(MAILIMF_ADDRESS_GROUP, NULL, g); + /* do the things */ + mailimf_address_free(a_g); + + return 0; +} + +/* display the content of an address */ + +#include <libetpan/libetpan.h> + +void display_address(struct mailimf_address * a) +{ + clistiter * cur; + + switch (a->ad_type) { + case MAILIMF_ADDRESS_GROUP: + display_mailimf_group(a->ad_data.ad_group); + break; + + case MAILIMF_ADDRESS_MAILBOX: + display_mailimf_mailbox(a->ad_data.ad_mailbox); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-MAILBOX-LIST" +>mailimf_mailbox_list - list of mailboxes</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_mailbox_list { + clist * mb_list; /* list of (struct mailimf_mailbox *), != NULL */ +}; + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new(clist * mb_list); + +void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list); + </PRE +><P +> This is a list of mailboxes. + </P +><P +> <B +CLASS="COMMAND" +>mb_list</B +> is a list of mailboxes. This is a + <B +CLASS="COMMAND" +>clist</B +> which elements are of type + mailimf_mailbox (see <A +HREF="#MAILIMF-MAILBOX" +>the Section called <I +>mailimf_mailbox - mailbox</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_list_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_list_free()</B +> frees memory used by the + structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN480" +></A +><P +><B +>Example 3-4. Creation and display of mailimf_mailbox_list</B +></P +><PRE +CLASS="PROGRAMLISTING" +>/* creates a list of mailboxes with two mailboxes */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_group * g; + char * display_name; + struct mailimf_mailbox_list * mb_list; + clist * list; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + list = clist_append(mb); + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + list = clist_append(mb); + + mb_list = mailimf_mailbox_list_new(list); + /* do the things */ + mailimf_mailbox_list_free(mb_list); + + return 0; +} + +/* display a list of mailboxes */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_mailbox_list(struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + display_mailbox(mb); + printf("\n"); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-ADDRESS-LIST" +>mailimf_address_list - list of addresses</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_address_list { + clist * ad_list; /* list of (struct mailimf_address *), != NULL */ +}; + +struct mailimf_address_list * +mailimf_address_list_new(clist * ad_list); + +void mailimf_address_list_free(struct mailimf_address_list * addr_list); + </PRE +><P +> This is a list of addresses. + </P +><P +> <B +CLASS="COMMAND" +>ad_list</B +> is a list of addresses. This is a + <B +CLASS="COMMAND" +>clist</B +> which elements are + of type mailimf_address (see <A +HREF="#MAILIMF-ADDRESS" +>the Section called <I +>mailimf_address - address</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_address_list_new()</B +> creates and + initializes a data structure with + a value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_address_list_free()</B +> frees memory + used by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN495" +></A +><P +><B +>Example 3-5. creation and display of list of addresses</B +></P +><PRE +CLASS="PROGRAMLISTING" +>/* creates a list of addresses with two addresses */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_address_list * addr_list; + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + list = clist_append(addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + list = clist_append(addr); + + addr_list = mailimf_address_list_new(list); + /* do the things */ + mailimf_address_list_free(mb_list); + + return 0; +} + +/* display a list of addresses */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_address_list(struct mailimf_address_list * addr_list) +{ + clistiter * cur; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + display_address(addr); + printf("\n"); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-GROUP" +>mailimf_group - named group of mailboxes</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_group { + char * grp_display_name; /* != NULL */ + struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */ +}; + +struct mailimf_group * +mailimf_group_new(char * grp_display_name, + struct mailimf_mailbox_list * grp_mb_list); + +void mailimf_group_free(struct mailimf_group * group); + </PRE +><P +> This is a list of mailboxes tagged with a name. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN502" +></A +><P +><B +>Example 3-6. example of group</B +></P +><PRE +CLASS="PROGRAMLISTING" +> they play music: <steve@morse.foo>, <neal@morse.foo>, + <yngwie@malmsteen.bar>, <michael@romeo.bar>; + </PRE +></DIV +><P +> <B +CLASS="COMMAND" +>grp_display_name</B +> is the name that will be + displayed for this group, + for example '<B +CLASS="COMMAND" +>group_name</B +>' in + '<B +CLASS="COMMAND" +>group_name: address1@domain1, + address2@domain2;</B +>'. + This must be allocated with malloc(). + <B +CLASS="COMMAND" +>grp_mb_list</B +> is a list of mailboxes + (see <A +HREF="#MAILIMF-MAILBOX-LIST" +>the Section called <I +>mailimf_mailbox_list - list of mailboxes</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_group_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_group_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN515" +></A +><P +><B +>Example 3-7. creation and display of a group</B +></P +><PRE +CLASS="PROGRAMLISTING" +>/* creates an empty group */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_group * g; + char * display_name; + + display_name = strdup("undisclosed-recipient"); + g = mailimf_group_new(display_name, NULL); + /* do the things */ + mailimf_group_free(g); +} + +/* creates a group with two mailboxes */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_group * g; + char * display_name; + struct mailimf_mailbox_list * mb_list; + struct mailimf_mailbox * mb; + clist * list; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + list = clist_append(mb); + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + list = clist_append(mb); + + mb_list = mailimf_mailbox_list_new(list); + + display_name = strdup("my_group"); + g = mailimf_group_new(display_name, mb_list); + /* do the things */ + mailimf_group_free(g); + + return 0; +} + +/* display content of group */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_group(struct mailimf_group * group) +{ + printf("name of the group: %s\n", a->group->display_name); + for(cur = clist_begin(a->group->mb_list->list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + display_mailbox(mb); + printf("\n"); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-DATE-TIME" +>mailimf_date_time - date of a message</A +></H3 +><P +>#include <libetpan/libetpan.h> + +struct mailimf_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +struct mailimf_date_time * +mailimf_date_time_new(int dt_day, int dt_month, int dt_year, + int dt_hour, int dt_min, int dt_sec, int dt_zone); + +void mailimf_date_time_free(struct mailimf_date_time * date_time); + </P +><P +> This is the date and time of a message. + For example : + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN522" +></A +><P +><B +>Example 3-8. example of date</B +></P +><PRE +CLASS="PROGRAMLISTING" +>Thu, 11 Dec 2003 00:15:02 +0100. + </PRE +></DIV +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>dt_day</B +> is the day of month (1 to 31) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dt_month</B +> (1 to 12) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dt_year</B +> (4 digits) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dt_hour</B +> (0 to 23) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dt_min</B +> (0 to 59) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dt_sec</B +> (0 to 59) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dt_zone</B +> (this is the decimal value that + we can read, for example: for + '<B +CLASS="COMMAND" +>-0200</B +>', the value is + <B +CLASS="COMMAND" +>-200</B +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_date_time_new()</B +> creates and + initializes a date structure with a value. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_date_time_free()</B +> frees memory used + by the structure. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN553" +></A +><P +><B +>Example 3-9. creation and display of date</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_date_time * d; + + d = mailimf_date_time_new(9, 5, 2003, 3, 01, 40, -0200); + /* do the things */ + mailimf_date_time_free(d); + + return 0; +} + +/* display the date */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_date(struct mailimf_date_time * d) +{ + printf("%02i/%02i/%i %02i:%02i:%02i %+04i\n", + d->dt_day, d->dt_month, d->dt_year, + d->dt_hour, d->dt_min, d->dt_sec, d->dt_zone); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-ORIG-DATE" +>mailimf_orig_date - parsed content of date header</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_orig_date { + struct mailimf_date_time * dt_date_time; /* != NULL */ +}; + +struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time * + dt_date_time); + +void mailimf_orig_date_free(struct mailimf_orig_date * orig_date); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Date</B +> or + <B +CLASS="COMMAND" +>Resent-Date</B +>. + It encapsulates a mailimf_date_time + </P +><P +> <B +CLASS="COMMAND" +>dt_date_time</B +> is the parsed date + (see <A +HREF="#MAILIMF-DATE-TIME" +>the Section called <I +>mailimf_date_time - date of a message</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_orig_date_new()</B +> creates and + initializes a data structure with + a value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_orig_date_free()</B +> frees memory used + by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN569" +></A +><P +><B +>Example 3-10. creation and display of Date field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_date_time * d; + struct mailimf_orig_date * date; + + d = mailimf_date_time_new(9, 5, 2003, 3, 01, 40, -0200); + date = mailimf_orig_date_new(d); + /* do the things */ + mailimf_orig_date_free(date); + + return 0; +} + +/* display date header */ + +#include <libetpan/libetpan.h> + +void display_orig_date(struct mailimf_orig_date * orig_date) +{ + display_date_time(d->dt_date_time); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-FROM" +>mailimf_from - parsed content of From header</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_from { + struct mailimf_mailbox_list * frm_mb_list; /* != NULL */ +}; + +struct mailimf_from * +mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list); + +void mailimf_from_free(struct mailimf_from * from); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>From</B +> or + <B +CLASS="COMMAND" +>Resent-From</B +>. + </P +><P +> <B +CLASS="COMMAND" +>frm_mb_list</B +> is the parsed mailbox list + (see <A +HREF="#MAILIMF-MAILBOX-LIST" +>the Section called <I +>mailimf_mailbox_list - list of mailboxes</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_from_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_from_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN585" +></A +><P +><B +>Example 3-11. creation and display of a From header</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + /* do the things */ + mailimf_from_free(from); + + return 0; +} + +/* display content of from header */ + +#include <libetpan/libetpan.h> + +void display_from(struct mailimf_from * from) +{ + display_mailbox_list(from->frm_mb_list); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-SENDER" +>mailimf_sender - parsed content of Sender header</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_sender { + struct mailimf_mailbox * snd_mb; /* != NULL */ +}; + +struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb); + +void mailimf_sender_free(struct mailimf_sender * sender); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Sender</B +> or + <B +CLASS="COMMAND" +>Resent-Sender</B +>. + </P +><P +> <B +CLASS="COMMAND" +>snd_mb</B +> is the parsed mailbox + (see <A +HREF="#MAILIMF-MAILBOX" +>the Section called <I +>mailimf_mailbox - mailbox</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_sender_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_sender_free()</B +> This function frees + memory used by the structure and substructures + will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN601" +></A +><P +><B +>Example 3-12. creation and display of Sender field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + + sender = mailimf_sender_new(mb); + /* do the things */ + mailimf_sender_free(sender); + + return 0; +} + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_sender(struct mailimf_sender * sender) +{ + display_mailbox(sender->snd_mb); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-REPLY-TO" +>mailimf_reply_to - parsed content of Reply-To header</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_reply_to { + struct mailimf_address_list * rt_addr_list; /* != NULL */ +}; + +struct mailimf_reply_to * +mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list); + +void mailimf_reply_to_free(struct mailimf_reply_to * reply_to); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Reply-To</B +>. + </P +><P +> <B +CLASS="COMMAND" +>addr_list</B +> is the parsed address list + (see <A +HREF="#MAILIMF-ADDRESS-LIST" +>the Section called <I +>mailimf_address_list - list of addresses</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_reply_to_new()</B +> creates and + initializes a data structure with a value. Structures given + as argument are referenced by the created object and will be + freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_reply_to_free()</B +> frees memory used + by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN616" +></A +><P +><B +>Example 3-13. creation and display of Reply-To field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_reply_to * reply_to; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + reply_to = mailimf_reply_to_new(addr_list); + /* do the things */ + mailimf_reply_to_free(reply_to); + + return 0; +} + +/* display Reply-To header */ + +#include <libetpan/libetpan.h> + +void display_reply_to(struct mailimf_reply_to * reply_to) +{ + display_address_list(reply_to->addr_list); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-TO" +>mailimf_to - parsed content of To header</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +> struct mailimf_to { + struct mailimf_address_list * to_addr_list; /* != NULL */ +}; + +struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list); + +void mailimf_to_free(struct mailimf_to * to); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>To</B +> or + <B +CLASS="COMMAND" +>Resent-To</B +>. + </P +><P +> <B +CLASS="COMMAND" +>to_addr_list</B +> is the parsed address list + (see <A +HREF="#MAILIMF-ADDRESS-LIST" +>the Section called <I +>mailimf_address_list - list of addresses</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_to_new()</B +> creates and initializes a + data structure with a value. Structures given as argument + are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_to_free()</B +> frees memory used by the + structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN632" +></A +><P +><B +>Example 3-14. creation and display of To field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + /* do the things */ + mailimf_to_free(to); + + return 0; +} + +/* display To header */ + +#include <libetpan/libetpan.h> + +void display_to(struct mailimf_to * to) +{ + display_address_list(to->to_addr_list); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-CC" +>mailimf_cc - parsed content of Cc</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_cc { + struct mailimf_address_list * cc_addr_list; /* != NULL */ +}; + +struct mailimf_cc * +mailimf_cc_new(struct mailimf_address_list * cc_addr_list); + +void mailimf_cc_free(struct mailimf_cc * cc);</PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Cc</B +> or + <B +CLASS="COMMAND" +>Resent-Cc</B +>. + </P +><P +> <B +CLASS="COMMAND" +>cc_addr_list</B +> is the parsed address list + (see <A +HREF="#MAILIMF-ADDRESS-LIST" +>the Section called <I +>mailimf_address_list - list of addresses</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_cc_new()</B +> creates and initializes a + data structure with a value. Structures given as argument + are referenced by the created object and will be freed if + the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_cc_free()</B +> This function frees + memory used by the structure and substructures will also be + released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN648" +></A +><P +><B +>Example 3-15. creation and display of Cc field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + cc = mailimf_cc_new(addr_list); + /* do the things */ + mailimf_cc_free(cc); + + return 0; +} + +/* display content of Cc field */ + +#include <libetpan/libetpan.h> + +void display_cc(struct mailimf_cc * cc) +{ + display_address_list(cc->cc_addr_list); +} + + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-BCC" +>mailimf_bcc - parsed content of Bcc field</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_bcc { + struct mailimf_address_list * bcc_addr_list; /* can be NULL */ +}; + +struct mailimf_bcc * +mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list); + +void mailimf_bcc_free(struct mailimf_bcc * bcc); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Bcc</B +> or + <B +CLASS="COMMAND" +>Resent-Bcc</B +>. + </P +><P +> <B +CLASS="COMMAND" +>bcc_addr_list</B +> is the parsed address list + (see <A +HREF="#MAILIMF-ADDRESS-LIST" +>the Section called <I +>mailimf_address_list - list of addresses</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_bcc_new()</B +> creates and initializes a + data structure with a value. Structures given as argument + are referenced by the created object and will be freed if + the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_bcc_free()</B +> frees memory used by the + structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN664" +></A +><P +><B +>Example 3-16. creation and display of Bcc field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>/* create visible Bcc */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + bcc = mailimf_bcc_new(addr_list); + /* do the things */ + mailimf_bcc_free(bcc); + + return 0; +} + +/* create unvisible Bcc */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_bcc * bcc; + + bcc = mailimf_bcc_new(NULL); + /* do the things */ + mailimf_bcc_free(bcc); + + return 0; +} + +/* display content of Bcc field */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_bcc(struct mailimf_bcc * bcc) +{ + if (bcc->addr_list == NULL) { + printf("hidden Bcc\n"); + } + else { + display_address_list(bcc->bcc_addr_list); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-MESSAGE-ID" +>mailimf_message_id - parsed content of Message-ID header</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_message_id { + char * mid_value; /* != NULL */ +}; + +struct mailimf_message_id * mailimf_message_id_new(char * mid_value); + +void mailimf_message_id_free(struct mailimf_message_id * message_id); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Message-ID</B +> + or <B +CLASS="COMMAND" +>Resent-Message-ID</B +>. For example : + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN673" +></A +><P +><B +>Example 3-17. example of Message-ID</B +></P +><PRE +CLASS="PROGRAMLISTING" +>Message-ID: <200312100009.43592@c01n-c01n.plop.P4N>> + </PRE +></DIV +><P +> <B +CLASS="COMMAND" +>mid_value</B +> is the message identifier. + It is not enclosed by angle bracket. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_message_id_new()</B +> This function + creates and initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> The given string is allocated with + <B +CLASS="COMMAND" +>malloc()</B +> and is not enclosed by angle bracket. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_message_id_free()</B +> frees memory + used by the structure and substructures will also be + released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN684" +></A +><P +><B +>Example 3-18. creation and display of Message-ID field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_message_id * msg_id; + char * id; + + id = strdup("1037197913.3dd26259752fa@imp.free.fr"); + msg_id = mailimf_message_id_new(id); + /* do the things */ + mailimf_message_id_free(msg_id); + + return 0; +} + +/* display message id */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_message_id(struct mailimf_message_id * msg_id) +{ + printf("%s\n", msg_id->mid_value); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-IN-REPLY-TO" +>mailimf_in_reply_to - parsed content of In-Reply-To + field</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_in_reply_to { + clist * mid_list; /* list of (char *), != NULL */ +}; + +struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list); + +void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to); + </PRE +><P +> content of a header <B +CLASS="COMMAND" +>In-Reply-To</B +>. + For example : + </P +><PRE +CLASS="PROGRAMLISTING" +>In-Reply-To: <etPan.3fd5fa29.4c3901c1.6b39@homer> + </PRE +><P +> <B +CLASS="COMMAND" +>mid_list</B +> is a <B +CLASS="COMMAND" +>clist</B +> + in which elements are message identifiers. + their types are <B +CLASS="COMMAND" +>(char *)</B +> and they are + allocated with <B +CLASS="COMMAND" +>malloc()</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_in_reply_to_new()</B +> creates and + initializes a data structure with a value. Structures given + as argument are referenced by the created object and will be + freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_in_reply_to_free()</B +> frees memory + used by the structure and substructures will also be + released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN702" +></A +><P +><B +>Example 3-19. creation and display of In-Reply-To field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_in_reply_to * in_reply_to; + clist * msg_id_list; + + msg_id_list = clist_new(); + clist_append(msg_id_list, + strdup("etPan.3ebbcc18.4014197f.bc1@homer.invalid")); + + in_reply_to = mailimf_in_reply_to_new(msg_id_list); + /* do the things */ + mailimf_in_reply_to_free(in_reply_to); + + return 0; +} + +/* display the content of mailimf_in_reply_to */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_in_reply_to(struct mailimf_in_reply_to * in_reply_to) +{ + clistiter * cur; + + for(cur = clist_begin(in_reply_to->mid_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * str; + + str = clist_content(cur); + + printf("%s\n", str); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-REFERENCES" +>mailimf_references - parsed content of References field</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_references { + clist * mid_list; /* list of (char *) */ + /* != NULL */ +}; + +struct mailimf_references * mailimf_references_new(clist * mid_list); + +void mailimf_references_free(struct mailimf_references * references); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>References</B +>. + For example : + </P +><PRE +CLASS="PROGRAMLISTING" +>In-Reply-To: <etPan.3fd5fa29.4c3901c1.6b39@homer> + <3FD5FA78.A1D98E7@oleane.net> + <etPan.3fd5fc69.2b349482.730e@homer> + </PRE +><P +> <B +CLASS="COMMAND" +>mid_list</B +> is a <B +CLASS="COMMAND" +>clist</B +> + in which elements are message identifiers. + their types are <B +CLASS="COMMAND" +>(char *)</B +> and they are + allocated with <B +CLASS="COMMAND" +>malloc()</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_references_new()</B +> creates and + initializes a data structure with a value. Structures given + as argument are referenced by the created object and will be + freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_references_free()</B +> frees memory + used by the structure and substructures will also be + released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN720" +></A +><P +><B +>Example 3-20. creation and display of References field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_references * ref; + clist * msg_id_list; + + msg_id_list = clist_new(); + clist_append(msg_id_list, + strdup("200304280144.23633.wim.delvaux@adaptiveplanet.com")); + clist_append(msg_id_list, + strdup("200304301153.19688.wim.delvaux@adaptiveplanet.com")); + clist_append(msg_id_list, + strdup("etPan.3eb29de4.5fc4d652.3f83@homer")); + + ref = mailimf_references_new(msg_id_list); + /* do the things */ + mailimf_in_reply_to_free(ref); + + return 0; +} + +/* display references */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_references(struct mailimf_references * ref) +{ + clistiter * cur; + + for(cur = clist_begin(ref->mid_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * msg_id; + + msg_id = clist_content(cur); + + printf("%s\n", msg_id); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-SUBJECT" +>mailimf_subject - parsed content of Subject field</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_subject { + char * sbj_value; /* != NULL */ +}; + +struct mailimf_subject * mailimf_subject_new(char * sbj_value); + +void mailimf_subject_free(struct mailimf_subject * subject);</PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Subject</B +>. + </P +><P +> <B +CLASS="COMMAND" +>sbj_value</B +> is the value of the field. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_subject_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_subject_free</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN734" +></A +><P +><B +>Example 3-21. creation and display of Subject field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_subject * subject; + + subject = mailimf_subject_new(strdup("example of subject")); + /* do the things */ + mailimf_subject_free(subject); + + return 0; +} + +/* display subject header */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_subject(struct mailimf_subject * subject) +{ + printf("%s\n", subject->value); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-COMMENTS" +>mailimf_comments - parsed content of Comments field</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_comments { + char * cm_value; /* != NULL */ +}; + +struct mailimf_comments * mailimf_comments_new(char * cm_value); + +void mailimf_comments_free(struct mailimf_comments * comments); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Comments</B +>. + </P +><P +> <B +CLASS="COMMAND" +>cm_value</B +> is the value of the field. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_comments_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_comments_free()</B +> frees memory used + by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN748" +></A +><P +><B +>Example 3-22. creation and display of Comment field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_comments * comments; + + comments = mailimf_comments_new(strdup("example of comment")); + /* do the things */ + mailimf_comments_free(comments); + + return 0; +} + +/* display the content of a comments */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_comments(struct mailimf_comments * comments) +{ + printf("%s\n", comments->cm_value); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-KEYWORDS" +>mailimf_keywords - parsed content of Keywords field</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_keywords { + clist * kw_list; /* list of (char *), != NULL */ +}; + +struct mailimf_keywords * mailimf_keywords_new(clist * kw_list); + +void mailimf_keywords_free(struct mailimf_keywords * keywords); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Keywords</B +>. + </P +><P +> <B +CLASS="COMMAND" +>kw_list</B +> is the list of keywords. This is + a list of <B +CLASS="COMMAND" +>(char *)</B +> allocated with malloc(). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_keywords_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_keywords_free()</B +> frees memory used + by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN763" +></A +><P +><B +>Example 3-23. creation and display of Keywords field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_keywords * keywords; + clist * list; + + list = clist_new(); + clist_append(list, strdup("sauerkraut")); + clist_append(list, strdup("potatoes")); + clist_append(list, strdup("cooking")); + + keywords = mailimf_keywords_new(list); + /* do the things */ + mailimf_keywords_free(keywords); + + return 0; +} + +/* display the content of mailimf_in_reply_to */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_keywords(struct mailimf_keywords * kw) +{ + clistiter * cur; + + for(cur = clist_begin(kw->kw_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * str; + + str = clist_content(cur); + + printf("%s\n", str); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-RETURN" +>mailimf_return - parsed content of Return-Path field</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_return { + struct mailimf_path * ret_path; /* != NULL */ +}; + +struct mailimf_return * +mailimf_return_new(struct mailimf_path * ret_path); + +void mailimf_return_free(struct mailimf_return * return_path); + </PRE +><P +> This is the content of a header + <B +CLASS="COMMAND" +>Return-Path</B +>. + </P +><P +> <B +CLASS="COMMAND" +>ret_path</B +> is the parsed value of Return-Path + (see <A +HREF="#MAILIMF-PATH" +>the Section called <I +>mailimf_path - address in Return-Path field</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_return_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_return_free()</B +> frees memory used + by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN778" +></A +><P +><B +>Example 3-24. creation and display of Return-Path field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_path * path; + struct mailimf_return * r; + + path = mailimf_path_new(strdup("dinh.viet.hoa@free.fr")); + r = mailimf_return_new(path); + /* do the things */ + mailimf_return_free(r); + + return 0; +} + +/* display return path */ + +#include <libetpan/libetpan.h> + +void display_return(struct mailimf_return * r) +{ + display_path(r->ret_path); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-PATH" +>mailimf_path - address in Return-Path field</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_path { + char * pt_addr_spec; /* can be NULL */ +}; + +struct mailimf_path * mailimf_path_new(char * pt_addr_spec); + +void mailimf_path_free(struct mailimf_path * path); + </PRE +><P +> This is the encapsulation of address specifier for + <B +CLASS="COMMAND" +>Return-Path</B +> content. + </P +><P +> <B +CLASS="COMMAND" +>pt_addr_spec</B +> is a mailbox destination. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_path_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> The given string is allocated with + <B +CLASS="COMMAND" +>malloc()</B +>. This is a address + specifier. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_path_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN794" +></A +><P +><B +>Example 3-25. Creation and display of return path</B +></P +><PRE +CLASS="PROGRAMLISTING" +> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_path * path; + + path = mailimf_path_new(strdup("dinh.viet.hoa@free.fr")); + /* do the things */ + mailimf_path_free(r); + + return 0; +} + +/* display return path */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_path(struct mailimf_path * path) +{ + printf("%s\n", path->pt_addr_spec); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-OPTIONAL-FIELD" +>mailimf_optional_field - non-standard header</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_optional_field { + char * fld_name; /* != NULL */ + char * fld_value; /* != NULL */ +}; + +struct mailimf_optional_field * +mailimf_optional_field_new(char * fld_name, char * fld_value); + +void mailimf_optional_field_free(struct mailimf_optional_field * opt_field); + </PRE +><P +> This is a non-standard header or unparsed header. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fld_name</B +> is the name of the header + field. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_value</B +> is the value of the header + field. + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_optional_field_new()</B +> This + function creates and initializes a data structure with a + value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + </P +><P +> field name and field value have to be allocated with + <B +CLASS="COMMAND" +>malloc()</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_optional_field_free()</B +> This + function frees memory used by the structure and + substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN814" +></A +><P +><B +>Example 3-26. creation and display of non-standard fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_optional_field * opt; + + opt = mailimf_optional_field_new(strdup("X-My-Field"), strdup("my value")); + /* do the things */ + mailimf_optional_field_free(opt); + + return 0; +} + +/* display the optional field */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_optional_field(struct mailimf_optional_field * opt) +{ + printf("%s: %s\n", opt->fld_name, opt->fld_value); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-FIELD" +>mailimf_field - header field</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILIMF_FIELD_NONE, /* on parse error */ + MAILIMF_FIELD_RETURN_PATH, /* Return-Path */ + MAILIMF_FIELD_RESENT_DATE, /* Resent-Date */ + MAILIMF_FIELD_RESENT_FROM, /* Resent-From */ + MAILIMF_FIELD_RESENT_SENDER, /* Resent-Sender */ + MAILIMF_FIELD_RESENT_TO, /* Resent-To */ + MAILIMF_FIELD_RESENT_CC, /* Resent-Cc */ + MAILIMF_FIELD_RESENT_BCC, /* Resent-Bcc */ + MAILIMF_FIELD_RESENT_MSG_ID, /* Resent-Message-ID */ + MAILIMF_FIELD_ORIG_DATE, /* Date */ + MAILIMF_FIELD_FROM, /* From */ + MAILIMF_FIELD_SENDER, /* Sender */ + MAILIMF_FIELD_REPLY_TO, /* Reply-To */ + MAILIMF_FIELD_TO, /* To */ + MAILIMF_FIELD_CC, /* Cc */ + MAILIMF_FIELD_BCC, /* Bcc */ + MAILIMF_FIELD_MESSAGE_ID, /* Message-ID */ + MAILIMF_FIELD_IN_REPLY_TO, /* In-Reply-To */ + MAILIMF_FIELD_REFERENCES, /* References */ + MAILIMF_FIELD_SUBJECT, /* Subject */ + MAILIMF_FIELD_COMMENTS, /* Comments */ + MAILIMF_FIELD_KEYWORDS, /* Keywords */ + MAILIMF_FIELD_OPTIONAL_FIELD, /* other field */ +}; + +struct mailimf_field { + int fld_type; + union { + struct mailimf_return * fld_return_path; /* can be NULL */ + struct mailimf_orig_date * fld_resent_date; /* can be NULL */ + struct mailimf_from * fld_resent_from; /* can be NULL */ + struct mailimf_sender * fld_resent_sender; /* can be NULL */ + struct mailimf_to * fld_resent_to; /* can be NULL */ + struct mailimf_cc * fld_resent_cc; /* can be NULL */ + struct mailimf_bcc * fld_resent_bcc; /* can be NULL */ + struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */ + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ + struct mailimf_optional_field * fld_optional_field; /* can be NULL */ + } fld_data; +}; + +struct mailimf_field * +mailimf_field_new(int fld_type, + struct mailimf_return * fld_return_path, + struct mailimf_orig_date * fld_resent_date, + struct mailimf_from * fld_resent_from, + struct mailimf_sender * fld_resent_sender, + struct mailimf_to * fld_resent_to, + struct mailimf_cc * fld_resent_cc, + struct mailimf_bcc * fld_resent_bcc, + struct mailimf_message_id * fld_resent_msg_id, + struct mailimf_orig_date * fld_orig_date, + struct mailimf_from * fld_from, + struct mailimf_sender * fld_sender, + struct mailimf_reply_to * fld_reply_to, + struct mailimf_to * fld_to, + struct mailimf_cc * fld_cc, + struct mailimf_bcc * fld_bcc, + struct mailimf_message_id * fld_message_id, + struct mailimf_in_reply_to * fld_in_reply_to, + struct mailimf_references * fld_references, + struct mailimf_subject * fld_subject, + struct mailimf_comments * fld_comments, + struct mailimf_keywords * fld_keywords, + struct mailimf_optional_field * fld_optional_field); + +void mailimf_field_free(struct mailimf_field * field); + </PRE +><P +> This is one header field of a message. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>type</B +> is the type of the field. This define the + type of the field. + Only the corresponding field should be, then, + filled. The value of this field can be one of : + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RETURN_PATH</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_DATE</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_FROM</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_SENDER</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_TO</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_CC</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_BCC</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_MSG_ID</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_ORIG_DATE</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_FROM</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_SENDER</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_REPLY_TO</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_TO</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_CC</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_BCC</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_MESSAGE_ID</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_IN_REPLY_TO</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_REFERENCES</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_SUBJECT</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_COMMENTS</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_KEYWORDS</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_OPTIONAL_FIELD</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_return_path</B +> is the + parsed content of the Return-Path field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_RETURN_PATH</B +> + (see <A +HREF="#MAILIMF-RETURN" +>the Section called <I +>mailimf_return - parsed content of Return-Path field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_resent_date</B +> is the + parsed content of the Resent-Date field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_DATE</B +> + (see <A +HREF="#MAILIMF-ORIG-DATE" +>the Section called <I +>mailimf_orig_date - parsed content of date header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_resent_from</B +> is the + parsed content of the Resent-From field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_FROM</B +> + (see <A +HREF="#MAILIMF-FROM" +>the Section called <I +>mailimf_from - parsed content of From header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_resent_sender</B +> is the + parsed content of the Resent-Sender field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_SENDER</B +> + (see <A +HREF="#MAILIMF-SENDER" +>the Section called <I +>mailimf_sender - parsed content of Sender header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_resent_to</B +> is the parsed + content of the Resent-To field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_TO</B +> + (see <A +HREF="#MAILIMF-TO" +>the Section called <I +>mailimf_to - parsed content of To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_resent_cc</B +> is the parsed + content of the Resent-Cc field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_CC</B +> + (see <A +HREF="#MAILIMF-CC" +>the Section called <I +>mailimf_cc - parsed content of Cc</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_resent_bcc</B +> is the parsed + content of the Resent-Bcc field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_BCC</B +> + (see <A +HREF="#MAILIMF-BCC" +>the Section called <I +>mailimf_bcc - parsed content of Bcc field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_resent_msg_id</B +> is the + parsed content of the Resent-Message-ID field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_MSG_ID</B +> + (see <A +HREF="#MAILIMF-MESSAGE-ID" +>the Section called <I +>mailimf_message_id - parsed content of Message-ID header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_orig_date</B +> is the parsed + content of the Date field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_ORIG_DATE</B +> + (see <A +HREF="#MAILIMF-ORIG-DATE" +>the Section called <I +>mailimf_orig_date - parsed content of date header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_from</B +> is the parsed + content of the From field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_FROM</B +> + (see <A +HREF="#MAILIMF-FROM" +>the Section called <I +>mailimf_from - parsed content of From header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_sender</B +> is the parsed + content of the Sender field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_SENDER</B +> + (see <A +HREF="#MAILIMF-SENDER" +>the Section called <I +>mailimf_sender - parsed content of Sender header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_reply_to</B +> is the parsed + content of the Reply-To field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_REPLY_TO</B +> + (see <A +HREF="#MAILIMF-REPLY-TO" +>the Section called <I +>mailimf_reply_to - parsed content of Reply-To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_to</B +> is the parsed content + of the To field if type is + <B +CLASS="COMMAND" +>MAILIMF_FIELD_TO</B +> + (see <A +HREF="#MAILIMF-TO" +>the Section called <I +>mailimf_to - parsed content of To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_cc</B +> is the parsed content + of the Cc field if type is + <B +CLASS="COMMAND" +>MAILIMF_FIELD_CC</B +> + (see <A +HREF="#MAILIMF-CC" +>the Section called <I +>mailimf_cc - parsed content of Cc</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_bcc</B +> is the parsed + content of the Bcc field if type is + <B +CLASS="COMMAND" +>MAILIMF_FIELD_BCC</B +> + (see <A +HREF="#MAILIMF-BCC" +>the Section called <I +>mailimf_bcc - parsed content of Bcc field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_message_id</B +> is the parsed + content of the Message-ID field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_MESSAGE_ID</B +> + (see <A +HREF="#MAILIMF-MESSAGE-ID" +>the Section called <I +>mailimf_message_id - parsed content of Message-ID header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_in_reply_to</B +> is the + parsed content of the In-Reply-To field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_IN_REPLY_TO</B +> + (see <A +HREF="#MAILIMF-IN-REPLY-TO" +>the Section called <I +>mailimf_in_reply_to - parsed content of In-Reply-To + field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_references</B +> is the parsed + content of the References field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_REFERENCES</B +> + (see <A +HREF="#MAILIMF-REFERENCES" +>the Section called <I +>mailimf_references - parsed content of References field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_subject</B +> is the content + of the Subject field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_SUBJECT</B +> + (see <A +HREF="#MAILIMF-SUBJECT" +>the Section called <I +>mailimf_subject - parsed content of Subject field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_comments</B +> is the content of the + Comments field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_COMMENTS</B +> + (see <A +HREF="#MAILIMF-COMMENTS" +>the Section called <I +>mailimf_comments - parsed content of Comments field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_keywords</B +> is the parsed + content of the Keywords field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_KEYWORDS</B +> + (see <A +HREF="#MAILIMF-KEYWORDS" +>the Section called <I +>mailimf_keywords - parsed content of Keywords field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_optional_field</B +> is an + other field and is not parsed + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_OPTIONAL_FIELD</B +> + (see <A +HREF="#MAILIMF-OPTIONAL-FIELD" +>the Section called <I +>mailimf_optional_field - non-standard header</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_field_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_field_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN961" +></A +><P +><B +>Example 3-27. creation and display of field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_field * f; + struct mailimf_mailbox * mb; + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + /* do the things */ + mailimf_field_free(f); + + return 0; +} + +/* display content of the header */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_field(struct mailimf_field * field) +{ + switch (field->type) { + case MAILIMF_FIELD_RETURN_PATH: + printf("Return-Path:\n"); + display_return(field->fld_data.fld_return_path); + break; + case MAILIMF_FIELD_RESENT_DATE: + printf("Resent-Date:\n"); + display_orig_date(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_RESENT_FROM: + printf("Resent-From:\n"); + display_from(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_RESENT_SENDER: + printf("Resent-Sender:\n"); + display_sender(field->fld_data.fld_resent_sender); + break; + case MAILIMF_FIELD_RESENT_TO: + printf("Resent-To:\n"); + display_to(field->fld_data.fld_resent_to); + break; + case MAILIMF_FIELD_RESENT_CC: + printf("Resent-Cc:\n"); + display_from(field->fld_data.fld_resent_cc); + break; + case MAILIMF_FIELD_RESENT_BCC: + printf("Resent-Bcc:\n"); + display_from(field->fld_data.fld_resent_bcc); + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + printf("Resent-Message-ID:\n"); + display_message_id(field->fld_data.fld_resent_msg_id); + break; + case MAILIMF_FIELD_ORIG_DATE: + printf("Date:\n"); + display_orig_date(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + printf("From:\n"); + display_from(field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + printf("Sender:\n"); + display_sender(field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + printf("Reply-To:\n"); + display_reply_to(field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + printf("To:\n"); + display_to(field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + printf("Cc:\n"); + display_cc(field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + printf("Bcc:\n"); + display_bcc(field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + printf("Message-ID:\n"); + display_message_id(field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + printf("In-Reply-To:\n"); + display_in_reply_to(field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + printf("References:\n"); + display_references(field->fld_data.fld_references_to); + break; + case MAILIMF_FIELD_SUBJECT: + printf("Subject:\n"); + display_subject(field->fld_data.fld_subject); + break; + case MAILIMF_FIELD_COMMENTS: + printf("Comments:\n"); + display_comments(field->fld_data.fld_comments); + break; + case MAILIMF_FIELD_KEYWORDS: + printf("Keywords:\n"); + display_keywords(field->fld_data.fld_keywords); + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + printf("[optional field]:\n"); + display_optional_field(field->fld_data.fld_optional_field); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-FIELDS" +>mailimf_fields - list of header fields</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_fields { + clist * fld_list; /* list of (struct mailimf_field *), != NULL */ +}; + +struct mailimf_fields * mailimf_fields_new(clist * fld_list); + +void mailimf_fields_free(struct mailimf_fields * fields); + </PRE +><P +> This is the list of header fields of a message. + </P +><P +> <B +CLASS="COMMAND" +>fld_list</B +> is a list of header fields. This + is a <B +CLASS="COMMAND" +>clist</B +> which elements are + of type <B +CLASS="COMMAND" +>mailimf_field</B +> (see <A +HREF="#MAILIMF-FIELD" +>the Section called <I +>mailimf_field - header field</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_fields_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_fields_free()</B +> frees memory used + by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN977" +></A +><P +><B +>Example 3-28. creation and display of header fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_field * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + /* do the things */ + mailimf_fields_free(fields); + + return 0; +} + +/* display list of headers */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_fields(struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(field->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_field * f; + + f = clist_content(cur); + + display_field(f); + printf("\n"); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-BODY" +>mailimf_body - message body without headers</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_body { + const char * bd_text; /* != NULL */ + size_t bd_size; +}; + +struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size); + +void mailimf_body_free(struct mailimf_body * body); + </PRE +><P +> This is the text content of a message (without headers). + </P +><P +> <P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>bd_text</B +> is the beginning of the + text part, it is a substring of an other string. + It is not necessarily zero terminated. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>bd_size</B +> is the size of the text part + </P +></LI +></UL +> + </P +><P +> <B +CLASS="COMMAND" +>mailimf_body_new()</B +> creates and + initializes a data structure with a value. + Text given as argument will <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> be released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_body_free()</B +> frees memory used by + the structure. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN997" +></A +><P +><B +>Example 3-29. creation and display of message body</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_body * b; + + b = mailimf_body_new("this is the content of the message", 34); + /* do the things */ + mailimf_body_free(b); + + return 0; +} + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_body(struct mailimf_body * b) +{ + char * text; + + text = malloc(b->size + 1); + strncpy(text, b->bd_text, b->bd_size); + text[b->size] = 0; + + puts(text); + printf("\n"); + + free(text); + + return 0; +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-MESSAGE" +>mailimf_message - parsed message</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_message { + struct mailimf_fields * msg_fields; /* != NULL */ + struct mailimf_body * msg_body; /* != NULL */ +}; + +struct mailimf_message * +mailimf_message_new(struct mailimf_fields * msg_fields, + struct mailimf_body * msg_body); + +void mailimf_message_free(struct mailimf_message * message); + </PRE +><P +> This is the message content (text and headers). + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>msg_fields</B +> is the header fields of + the message + (see <A +HREF="#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_body</B +> is the text part of the message + (see <A +HREF="#MAILIMF-BODY" +>the Section called <I +>mailimf_body - message body without headers</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_message_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_message_free()</B +> frees memory used + by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1017" +></A +><P +><B +>Example 3-30. creation and display of message</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_body * b; + struct mailimf_message * m; + struct mailimf_fields * fields; + struct mailimf_fields * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build text content */ + + b = mailimf_body_new("this is the content of the message", 34); + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + + /* build message */ + + m = mailimf_message_new(fields, b); + /* do the things */ + mailimf_message_free(m); + + return 0; +} + +/* display the message */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_message(struct mailimf_message * msg) +{ + display_fields(msg->msg_fields); + printf("\n"); + display_body(msg->msg_body); + printf("\n"); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-SINGLE-FIELDS" +>mailimf_single_fields - simplified fields</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_single_fields { + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ +}; + +struct mailimf_single_fields * +mailimf_single_fields_new(struct mailimf_fields * fields); + +void mailimf_single_fields_free(struct mailimf_single_fields * + single_fields); + +void mailimf_single_fields_init(struct mailimf_single_fields * single_fields, + struct mailimf_fields * fields);</PRE +><P +> Structure that contains some standard fields and allows access + to a given header without running through the list. + </P +><P +> mailimf_fields is the native structure that IMF module will use, + this module will provide an easier structure to use when + parsing fields. + mailimf_single_fields is an easier structure to get parsed fields, + rather than iteration over the list of fields + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fld_orig_date</B +> is the parsed "Date" + field + (see <A +HREF="#MAILIMF-ORIG-DATE" +>the Section called <I +>mailimf_orig_date - parsed content of date header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_from</B +> is the parsed "From" field + (see <A +HREF="#MAILIMF-FROM" +>the Section called <I +>mailimf_from - parsed content of From header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_sender</B +> is the parsed "Sender "field + (see <A +HREF="#MAILIMF-SENDER" +>the Section called <I +>mailimf_sender - parsed content of Sender header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>reply_to</B +> is the parsed "Reply-To" field + (see <A +HREF="#MAILIMF-REPLY-TO" +>the Section called <I +>mailimf_reply_to - parsed content of Reply-To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_to</B +> is the parsed "To" field + (see <A +HREF="#MAILIMF-TO" +>the Section called <I +>mailimf_to - parsed content of To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_cc</B +> is the parsed "Cc" field + (see <A +HREF="#MAILIMF-CC" +>the Section called <I +>mailimf_cc - parsed content of Cc</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_bcc</B +> is the parsed "Bcc" field + (see <A +HREF="#MAILIMF-BCC" +>the Section called <I +>mailimf_bcc - parsed content of Bcc field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_message_id</B +> is the parsed + "Message-ID" field. + (see <A +HREF="#MAILIMF-MESSAGE-ID" +>the Section called <I +>mailimf_message_id - parsed content of Message-ID header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_in_reply_to</B +> is the parsed + "In-Reply-To" field. + (see <A +HREF="#MAILIMF-IN-REPLY-TO" +>the Section called <I +>mailimf_in_reply_to - parsed content of In-Reply-To + field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_references</B +> is the parsed + "References" field. + (see <A +HREF="#MAILIMF-REFERENCES" +>the Section called <I +>mailimf_references - parsed content of References field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_subject</B +> is the parsed "Subject" field + (see <A +HREF="#MAILIMF-SUBJECT" +>the Section called <I +>mailimf_subject - parsed content of Subject field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_comments</B +> is the parsed "Comments" field + (see <A +HREF="#MAILIMF-COMMENTS" +>the Section called <I +>mailimf_comments - parsed content of Comments field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_keywords</B +> is the parsed "Keywords" field + (see <A +HREF="#MAILIMF-KEYWORDS" +>the Section called <I +>mailimf_keywords - parsed content of Keywords field</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_single_fields_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> be freed if the + object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_single_fields_free()</B +> frees memory + used by the structure and + substructures will <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> be + released. They should be released by the application. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_single_fields_init()</B +> will + initialize fill the data structure, using + the given argument (<B +CLASS="COMMAND" +>fields</B +>). The + interesting fields will be filled into + <B +CLASS="COMMAND" +>single_fields</B +>. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1088" +></A +><P +><B +>Example 3-31. using mailimf_single_fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_single_fields * single_fields; + struct mailimf_fields * fields; + struct mailimf_field * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + + /* create the single fields */ + single_fields = mailimf_single_fields_new(fields); + /* do the things */ + mailimf_single_fields_free(single_fields); + mailimf_fields_free(fields); + + return 0; +} + </PRE +></DIV +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1091" +></A +><P +><B +>Example 3-32. using mailimf_single_fields without memory allocation</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_single_fields single_fields; + struct mailimf_fields * fields; + struct mailimf_field * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + + /* fill the single fields */ + mailimf_fields_fields_init(&single_fields, fields); + /* do the things */ + mailimf_fields_free(fields); + + return 0; +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN1094" +>Parser functions</A +></H2 +><DIV +CLASS="SECT2" +><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-ADDRESS-LIST-PARSE" +>mailimf_address_list_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int +mailimf_address_list_parse(char * message, size_t length, + size_t * index, + struct mailimf_address_list ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_address_list_parse()</B +> parse a list + of addresses in RFC 2822 form. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing + the list of addresses. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given string + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> this is a pointer to the + start of the list of + addresses in the given string, + <B +CLASS="COMMAND" +>(* index)</B +> is modified to point + at the end of the parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILIMF-ADDRESS-LIST" +>the Section called <I +>mailimf_address_list - list of addresses</I +></A +>). + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1120" +></A +><P +><B +>Example 3-33. parsing a list of addresses</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_address_list * addr_list; + size_t current_index; + + current_index = 0; + r = mailimf_address_list_parse(mem, stat_info.st_size, + ¤t_index, &addr_list); + if (r == MAILIMF_NO_ERROR) { + display_address_list(addr_list); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_address_list_free(addr_list); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-ADDRESS-PARSE" +>mailimf_address_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int +mailimf_address_parse(char * message, size_t length, + size_t * index, + struct mailimf_address ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_address_parse()</B +> parse an address + in RFC 2822 form. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the + address. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse operation + is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILIMF-ADDRESS" +>the Section called <I +>mailimf_address - address</I +></A +>). + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1147" +></A +><P +><B +>Example 3-34. parsing an address</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_address * addr; + size_t current_index; + + current_index = 0; + r = mailimf_address_parse(mem, stat_info.st_size, + ¤t_index, &addr); + if (r == MAILIMF_NO_ERROR) { + display_address(addr); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_address_free(addr); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-BODY-PARSE" +>mailimf_body_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailimf_body_parse(char * message, size_t length, + size_t * index, + struct mailimf_body ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_body_parse()</B +> parse text body of a + message. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing + the message body part. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> this is a pointer to the start + of the message text part in + the given string, <B +CLASS="COMMAND" +>(* index)</B +> is + modified to point at the end + of the parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILIMF-BODY" +>the Section called <I +>mailimf_body - message body without headers</I +></A +>). + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1174" +></A +><P +><B +>Example 3-35. parsing a message body</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_body * b; + struct mailimf_fields * f; + size_t current_index; + size_t size; + + size = stat_info.st_size; + current_index = 0; + r = mailimf_fields_parse(mem, size, ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + r = mailimf_crlf_parse(mem, size, ¤t_index); + /* ignore parse error of crlf */ + + r = mailimf_body_parse(mem, size, ¤t_index, &b); + if (r == MAILIMF_NO_ERROR) { + + display_body(b); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_body_free(b); + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-ENVELOPE-AND-OPTIONAL-FIELDS-PARSE" +>mailimf_envelope_and_optional_fields_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int +mailimf_envelope_and_optional_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_envelope_and_optional_fields_parse()</B +> + returns a list of most useful headers (parsed). The other + headers will be placed in the list in a non-parsed form. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the header. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given string + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the header in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end + of the parsed data + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +></A +>). + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1201" +></A +><P +><B +>Example 3-36. parsing commonly used fields and return other fields + in a non-parsed form</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_envelope_and_optional_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-ENVELOPE-FIELDS-PARSE" +>mailimf_envelope_fields_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailimf_envelope_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_envelope_fields_parse()</B +> return a + list of most useful headers (parsed). + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the header + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given string + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the header in + the given string, <B +CLASS="COMMAND" +>(* index)</B +> is + modified to point at the end + of the parsed data + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +></A +>). + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1228" +></A +><P +><B +>Example 3-37. parsing commonly used fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_envelope_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-OPTIONAL-FIELDS-PARSE" +>mailimf_optional_fields_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int +mailimf_optional_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_optional_fields_parse</B +> return a + list of non-parsed headers. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the header + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given string + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the header in + the given string, <B +CLASS="COMMAND" +>(* index)</B +> is + modified to point at the end + of the parsed data + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +></A +>). + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1255" +></A +><P +><B +>Example 3-38. parsing optional fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_optional_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-FIELDS-PARSE" +>mailimf_fields_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailimf_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_fields_parse()</B +> parse headers of a + message. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the header + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given string + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the header in + the given string, <B +CLASS="COMMAND" +>(* index)</B +> is + modified to point at the end + of the parsed data + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +></A +>). + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1282" +></A +><P +><B +>Example 3-39. parsing header fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(f); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-IGNORE-FIELD-PARSE" +>mailimf_ignore_field_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailimf_ignore_field_parse(char * message, size_t length, + size_t * index); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_ignore_field_parse()</B +> skip the + next header. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the header + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given string + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the field to skip in + the given string, <B +CLASS="COMMAND" +>(* index)</B +> is + modified to point at the end + of the parsed data + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1304" +></A +><P +><B +>Example 3-40. skipping fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + size_t current_index; + + current_index = 0; + r = mailimf_ignore_field_parse(mem, stat_info.st_size, + ¤t_index); + if (r == MAILIMF_NO_ERROR) { + /* do the things */ + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-MAILBOX-LIST-PARSE" +>mailimf_mailbox_list_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int +mailimf_mailbox_list_parse(char * message, size_t length, + size_t * index, + struct mailimf_mailbox_list ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_list_parse()</B +> parse a list + of mailboxes in RFC 2822 form. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the + list of mailboxes. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the list of + mailboxes in the given string, + <B +CLASS="COMMAND" +>(* index)</B +> is modified to point + at the end of the parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +>. + (see <A +HREF="#MAILIMF-MAILBOX-LIST" +>the Section called <I +>mailimf_mailbox_list - list of mailboxes</I +></A +>) + </P +></LI +></UL +><P +> return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on + error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1329" +></A +><P +><B +>Example 3-41. parsing a list of mailboxes</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_mailbox_list * mb_list; + size_t current_index; + + current_index = 0; + r = mailimf_mailbox_list_parse(mem, stat_info.st_size, + ¤t_index, &mb_list); + if (r == MAILIMF_NO_ERROR) { + display_mailbox_list(mb_list); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_mailbox_list_free(mb_list); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-MAILBOX-PARSE" +>mailimf_mailbox_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +> +#include <libetpan/libetpan.h> + +int mailimf_mailbox_parse(char * message, size_t length, + size_t * index, + struct mailimf_mailbox ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_parse</B +> parse a mailbox in + RFC 2822 form. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the + mailbox. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the mailbox in the given string, + <B +CLASS="COMMAND" +>(* index)</B +> is modified to point + at the end of the parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +>. + (see <A +HREF="#MAILIMF-MAILBOX" +>the Section called <I +>mailimf_mailbox - mailbox</I +></A +>) + </P +></LI +></UL +><P +> return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on + error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1354" +></A +><P +><B +>Example 3-42. parsing a mailbox</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_mailbox_list * mb_list; + size_t current_index; + + current_index = 0; + r = mailimf_mailbox_parse(mem, stat_info.st_size, + ¤t_index, &mb_list); + if (r == MAILIMF_NO_ERROR) { + display_mailbox_list(mb_list); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_mailbox_free(mb_list); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-MESSAGE-PARSE" +>mailimf_message_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailimf_message_parse(char * message, size_t length, + size_t * index, + struct mailimf_message ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_message_parse</B +> parse message + (headers and body). + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing + the message content. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>param</B +> length this is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>param</B +> index this is a pointer to the + start of the message in + the given string, <B +CLASS="COMMAND" +>(* index)</B +> is + modified to point at the end + of the parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>param</B +> result the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILIMF-MESSAGE" +>the Section called <I +>mailimf_message - parsed message</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1378" +></A +><P +><B +>Example 3-43. parsing a message</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_message * m; + size_t current_index; + + current_index = 0; + r = mailimf_message_parse(mem, stat_info.st_size, + ¤t_index, &m); + if (r == MAILIMF_NO_ERROR) { + display_message(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_message_free(m); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN1381" +>Creation functions</A +></H2 +><DIV +CLASS="SECT2" +><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-MAILBOX-LIST-ADD" +>mailimf_mailbox_list</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new_empty(); + +int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list, + struct mailimf_mailbox * mb); + +int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list, + char * mb_str); + +int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list, + char * display_name, char * address); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_list_new_empty()</B +> creates a + new empty list of mailboxes. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_list_add</B +> adds a mailbox + to the list of mailboxes. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_list_add_parse</B +> adds a + mailbox given in form of a string to the list of mailboxes. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_list_add_mb</B +> adds a + mailbox given in form of a couple : display name, mailbox + address. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>mailbox_list</B +> is the list of mailboxes. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mb</B +> is a mailbox + (see <A +HREF="#MAILIMF-MAILBOX" +>the Section called <I +>mailimf_mailbox - mailbox</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mb_str</B +> is a mailbox given in the form + of a string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>display_name</B +> is the display name. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>address</B +> is the mailbox address. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1411" +></A +><P +><B +>Example 3-44. creating a list of mailboxes</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_mailbox * mb; + + mb_list = mailimf_mailbox_list_new_empty(); + + mb = mailimf_mailbox_new(strdup("DINH Viet Hoa"), + strdup("dinh.viet.hoa@free.fr")); + mailimf_mailbox_list_add(mb_list, mb); + + mailimf_mailbox_list_add_parse(mb_list, "foo bar <foo@bar.org>"); + + mailimf_mailbox_list_add_mb(mb_list, strdup("bar foo"), strdup("bar@foo.com")); + + mailimf_mailbox_list_free(mb_list); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-ADDRESS-LIST-ADD" +>mailimf_address_list</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_address_list * mailimf_address_list_new_empty(); + +int mailimf_address_list_add(struct mailimf_address_list * address_list, + struct mailimf_address * addr); + +int mailimf_address_list_add_parse(struct mailimf_address_list * address_list, + char * addr_str); + +int mailimf_address_list_add_mb(struct mailimf_address_list * address_list, + char * display_name, char * address); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_address_list_new_empty()</B +> creates a + new empty list of addresses. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_address_list_add</B +> adds an address + to the list of addresses. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_address_list_add_parse</B +> adds an + address given in form of a string to the list of addresses. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_address_list_add_mb</B +> adds a + mailbox given in form of a couple : display name, mailbox + address. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>address_list</B +> is the list of mailboxes. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>addr</B +> is an address. + (see <A +HREF="#MAILIMF-ADDRESS" +>the Section called <I +>mailimf_address - address</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>addr_str</B +> is an address given in the form of a + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>display_name</B +> is the display name. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>address</B +> is the mailbox address. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-FIELDS-ADD" +>mailimf_fields</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_fields * +mailimf_fields_new_empty(void); + +struct mailimf_field * mailimf_field_new_custom(char * name, char * value); + +int mailimf_fields_add(struct mailimf_fields * fields, + struct mailimf_field * field); + +int mailimf_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * msg_id, + clist * in_reply_to, + clist * references, + char * subject); + +struct mailimf_fields * +mailimf_fields_new_with_data_all(struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * message_id, + clist * in_reply_to, + clist * references, + char * subject); + +struct mailimf_fields * +mailimf_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + clist * in_reply_to, + clist * references, + char * subject); + +char * mailimf_get_message_id(void); + +struct mailimf_date_time * mailimf_get_current_date(void); + +int +mailimf_resent_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * resent_date, + struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +struct mailimf_fields * +mailimf_resent_fields_new_with_data_all(struct mailimf_date_time * + resent_date, struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +struct mailimf_fields * +mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc); + </PRE +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>from</B +> is the parsed content of the + From field + (see <A +HREF="#MAILIMF-FROM" +>the Section called <I +>mailimf_from - parsed content of From header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sender</B +> is the parsed content of the + Sender field + (see <A +HREF="#MAILIMF-SENDER" +>the Section called <I +>mailimf_sender - parsed content of Sender header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>reply_to</B +> is the parsed content of the + <B +CLASS="COMMAND" +>Reply-To</B +> field + (see <A +HREF="#MAILIMF-REPLY-TO" +>the Section called <I +>mailimf_reply_to - parsed content of Reply-To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>to</B +> is the parsed content of the + <B +CLASS="COMMAND" +>To</B +> field + (see <A +HREF="#MAILIMF-TO" +>the Section called <I +>mailimf_to - parsed content of To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>cc</B +> is the parsed content of the + <B +CLASS="COMMAND" +>Cc</B +> field + (see <A +HREF="#MAILIMF-CC" +>the Section called <I +>mailimf_cc - parsed content of Cc</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>bcc</B +> is the parsed content of the + <B +CLASS="COMMAND" +>Bcc</B +> field + (see <A +HREF="#MAILIMF-BCC" +>the Section called <I +>mailimf_bcc - parsed content of Bcc field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>message_id</B +> is the parsed content of + the <B +CLASS="COMMAND" +>Message-ID</B +> field + (see <A +HREF="#MAILIMF-MESSAGE-ID" +>the Section called <I +>mailimf_message_id - parsed content of Message-ID header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>in_reply_to</B +> is the parsed content of + the <B +CLASS="COMMAND" +>In-Reply-To</B +> field + (see <A +HREF="#MAILIMF-IN-REPLY-TO" +>the Section called <I +>mailimf_in_reply_to - parsed content of In-Reply-To + field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>references</B +> is the parsed content of + the <B +CLASS="COMMAND" +>References</B +> field + (see <A +HREF="#MAILIMF-REFERENCES" +>the Section called <I +>mailimf_references - parsed content of References field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>subject</B +> is the content of the + <B +CLASS="COMMAND" +>Subject</B +> field + (see <A +HREF="#MAILIMF-SUBJECT" +>the Section called <I +>mailimf_subject - parsed content of Subject field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>resent_date</B +> is the parsed content of + the <B +CLASS="COMMAND" +>Resent-Date</B +> field + (see <A +HREF="#MAILIMF-ORIG-DATE" +>the Section called <I +>mailimf_orig_date - parsed content of date header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>resent_from</B +> is the parsed content of + the <B +CLASS="COMMAND" +>Resent-From</B +> field + (see <A +HREF="#MAILIMF-FROM" +>the Section called <I +>mailimf_from - parsed content of From header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>resent_sender</B +> is the parsed content of the + <B +CLASS="COMMAND" +>Resent-Sender</B +> field + (see <A +HREF="#MAILIMF-SENDER" +>the Section called <I +>mailimf_sender - parsed content of Sender header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>resent_to</B +> is the parsed content of + the <B +CLASS="COMMAND" +>Resent-To</B +> field + (see <A +HREF="#MAILIMF-TO" +>the Section called <I +>mailimf_to - parsed content of To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>resent_cc</B +> is the parsed content of + the <B +CLASS="COMMAND" +>Resent-Cc</B +> field + (see <A +HREF="#MAILIMF-CC" +>the Section called <I +>mailimf_cc - parsed content of Cc</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>resent_bcc</B +> is the parsed content of the + <B +CLASS="COMMAND" +>Resent-Bcc</B +> field + (see <A +HREF="#MAILIMF-BCC" +>the Section called <I +>mailimf_bcc - parsed content of Bcc field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>resent_msg_id</B +> is the parsed content of the + <B +CLASS="COMMAND" +>Resent-Message-ID</B +> field + (see <A +HREF="#MAILIMF-MESSAGE-ID" +>the Section called <I +>mailimf_message_id - parsed content of Message-ID header</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_fields_new_empty()</B +> creates a new + empty set of headers. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_field_new_custom()</B +> creates a new + custom header. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_fields_add()</B +> adds a header to the + set of headers. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_fields_add_data()</B +> adds some headers + to the set of headers. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_fields_new_with_data_all()</B +> creates + a set of headers with some headers (including Date and + Message-ID). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_fields_new_with_data()</B +> creates a + set of headers with some headers (Date and Message-ID will + be generated). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_get_message_id()</B +> generates a + Message-ID. The result must be freed using + <B +CLASS="COMMAND" +>free()</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_get_current_date()</B +> generates a + Date. The result must be freed using + <B +CLASS="COMMAND" +>mailimf_date_time_free</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_resent_fields_add_data()</B +> adds some + resent headers to the set of headers. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_resent_fields_new_with_data_all()</B +> + creates a set of headers with some resent headers (including + Resent-Date and Resent-Message-ID). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_resent_fields_new_with_data()</B +> + creates a set of headers with some resent headers + (Resent-Date and Resent-Message-ID will be generated) + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1553" +></A +><P +><B +>Example 3-45. creation of header fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_field * field; + struct mailimf_date_time * date; + char * msg_id; + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + + fields = mailimf_fields_new_empty(); + field = mailimf_field_new_custom(strdup("X-Mailer"), strdup("my-mailer")); + mailimf_fields_add(fields, field); + + from = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet.hoa@free.fr"); + date = mailimf_get_current_date(); + msg_id = mailimf_get_message_id(); + to = mailimf_address_list_new_empty(); + mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org"); + + mailimf_fields_add_data(fields, date, from, NULL, NULL, to, NULL, NULL, + msg_id, NULL, NULL, strdup("hello")); + + /* do the things */ + + mailimf_fields_free(fields); +} + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + struct mailimf_date_time * date; + char * msg_id; + + from = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet.hoa@free.fr"); + to = mailimf_address_list_new_empty(); + mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org"); + date = mailimf_get_current_date(); + msg_id = mailimf_get_message_id(); + + fields = mailimf_fields_new_with_all_data(date, from, NULL, NULL, to, NULL, NULL, + msg_id, NULL, NULL, strdup("hello")); + + /* do the things */ + + mailimf_fields_free(fields); +} + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + + from = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet.hoa@free.fr"); + to = mailimf_address_list_new_empty(); + mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org"); + + fields = mailimf_fields_new_with_data(from, NULL, NULL, to, NULL, NULL, + NULL, NULL, strdup("hello")); + + /* do the things */ + + mailimf_fields_free(fields); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN1556" +>Rendering of messages</A +></H2 +><DIV +CLASS="SECT2" +><H3 +CLASS="SECT2" +><A +NAME="MAILIMF-FIELDS-WRITE" +>Header fields</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field); + </PRE +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>col</B +> current column is given for wrapping + purpose in <B +CLASS="COMMAND" +>(* col)</B +>, + the resulting columns will be returned.. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>f</B +> is the file descriptor. It can be + stdout for example. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fields</B +> is the header fields + (see <A +HREF="#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>field</B +> is a field + (see <A +HREF="#MAILIMF-FIELD" +>the Section called <I +>mailimf_field - header field</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_fields_write</B +> outputs the set of + header fields. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_envelope_fields_write</B +> outputs the + set of header fields except the optional fields. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_field_write</B +> outputs a header. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1583" +></A +><P +><B +>Example 3-46. rendering of fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + int col; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_imf_fields(); + + col = 0; + mailimf_fields_write(stdout, &col, fields); + + mailimf_fields_free(fields); +} + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + int col; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_imf_fields(); + + col = 0; + mailimf_envelope_fields_write(stdout, &col, fields); + + mailimf_fields_free(fields); +} + +int main(int argc, char ** argv) +{ + struct mailimf_field * field; + int col; + + field = mailimf_field_new_custom(strdup("X-Mailer"), strdup("my mailer")); + + col = 0; + mailimf_field_write(stdout, &col, field); + + mailimf_field_free(field); +} + </PRE +></DIV +></DIV +></DIV +></DIV +><DIV +CLASS="CHAPTER" +><HR><H1 +><A +NAME="AEN1586" +></A +>Chapter 4. MIME</H1 +><P +> libEtPan! implements a MIME message parser (also known as + messages with attachments or + multipart messages). This also allows to generate MIME messages. + </P +><DIV +CLASS="WARNING" +><P +></P +><TABLE +CLASS="WARNING" +BORDER="1" +WIDTH="100%" +><TR +><TD +ALIGN="CENTER" +><B +>Warning</B +></TD +></TR +><TR +><TD +ALIGN="LEFT" +><P +> All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + </P +><P +> allocation functions will return <B +CLASS="COMMAND" +>NULL</B +> on failure + + functions returning integer will be returning one of the + following error code: + <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +>, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_PARSE</B +>, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_MEMORY</B +>, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_INVAL</B +>, + or <B +CLASS="COMMAND" +>MAILIMF_ERROR_FILE</B +>. + </P +></TD +></TR +></TABLE +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN1598" +>Quick start</A +></H2 +><P +> You will need this module when you want to parse a MIME + message. + </P +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN1601" +>Parse MIME message</A +></H3 +><P +> You will use the following function : + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>mailmime_parse</B +> + (<A +HREF="#MAILIMF-ENVELOPE-AND-OPTIONAL-FIELDS-PARSE" +>the Section called <I +>mailimf_envelope_and_optional_fields_parse</I +> in Chapter 3</A +>) + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN1609" +>Render the MIME message</A +></H3 +><P +> Build your MIME message, then use + <B +CLASS="COMMAND" +>mailmime_write</B +> + (<A +HREF="#MAILMIME-WRITE" +>the Section called <I +>mailmime_write</I +></A +>) + to render a MIME message. + </P +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN1614" +>Data types</A +></H2 +><DIV +CLASS="SECT2" +><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-COMPOSITE-TYPE" +>mailmime_composite_type - Composite MIME type</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_COMPOSITE_TYPE_ERROR, + MAILMIME_COMPOSITE_TYPE_MESSAGE, + MAILMIME_COMPOSITE_TYPE_MULTIPART, + MAILMIME_COMPOSITE_TYPE_EXTENSION +}; + +struct mailmime_composite_type { + int ct_type; + char * ct_token; +}; + +struct mailmime_composite_type * +mailmime_composite_type_new(int ct_type, char * ct_token); + +void mailmime_composite_type_free(struct mailmime_composite_type * ct); + </PRE +><P +> This is a MIME composite type such as <B +CLASS="COMMAND" +>message</B +> or + <B +CLASS="COMMAND" +>multipart</B +>. + </P +><P +> <B +CLASS="COMMAND" +>ct_type</B +> can have one of the 3 following values : + <B +CLASS="COMMAND" +>MAILMIME_COMPOSITE_TYPE_MESSAGE</B +> when the + composite MIME type + is <B +CLASS="COMMAND" +>message</B +>, + <B +CLASS="COMMAND" +>MAILMIME_COMPOSITE_TYPE_MULTIPART</B +> when + the composite MIME type + is <B +CLASS="COMMAND" +> multipart</B +>, + <B +CLASS="COMMAND" +>MAILMIME_COMPOSITE_TYPE_EXTENSION</B +> for + other and <B +CLASS="COMMAND" +>ct_token</B +> is set + in this case. + <B +CLASS="COMMAND" +>MAILMIME_COMPOSITE_TYPE_ERROR</B +> is used + internally on parse error. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_composite_type_new()</B +> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_composite_type_free()</B +> frees + memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1635" +></A +><P +><B +>Example 4-1. create and display MIME composite type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(void) +{ + struct mailmime_composite_type * ct; + + ct = mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL); + + /* do your things ... */ + + mailmime_composite_type_free(ct); + + exit(EXIT_SUCCESS); +} + +void display_composite_type() +{ + switch (ct->type) { + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + printf("composite type is message\n"); + break; + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + printf("composite type is multipart\n"); + break; + case MAILMIME_COMPOSITE_TYPE_EXTENSION: + printf("composite type: %s\n", ct->ct_token); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-CONTENT" +>mailmime_content - MIME content type (Content-Type)</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_content { + struct mailmime_type * ct_type; + char * ct_subtype; + clist * ct_parameters; /* elements are (struct mailmime_parameter *) */ +}; + +struct mailmime_content * +mailmime_content_new(struct mailmime_type * ct_type, + char * ct_subtype, + clist * ct_parameters); + +void mailmime_content_free(struct mailmime_content * content); + </PRE +><P +> This is a MIME content type such as <B +CLASS="COMMAND" +>message/rfc822</B +> or + <B +CLASS="COMMAND" +>text/plain</B +>. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>ct_type</B +> is the main MIME type, + for example <B +CLASS="COMMAND" +>text</B +> in + <B +CLASS="COMMAND" +>plain/text</B +> + (see <A +HREF="#MAILMIME-TYPE" +>the Section called <I +>mailmime_type - MIME main type</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>ct_subtype</B +> is the MIME subtype, + for example <B +CLASS="COMMAND" +>plain</B +> in + <B +CLASS="COMMAND" +>plain/text</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>ct_parameters</B +> is the list of parameters for + the given MIME type. For example, for <B +CLASS="COMMAND" +>plain/text</B +>, + we can find <B +CLASS="COMMAND" +>charset=iso-8859-1</B +>, + <B +CLASS="COMMAND" +>format=flowed</B +>. Each element of the list + if of type <B +CLASS="COMMAND" +>struct mailmime_parameter *</B +> + (see <A +HREF="#MAILMIME-PARAMETER" +>the Section called <I +>mailmime_parameter - MIME type parameter</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailmime_content_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_content_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1667" +></A +><P +><B +>Example 4-2. Creation and display of MIME content type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(void) +{ + struct mailmime_content * content; + struct mailmime_type * type; + struct mailmime_discrete_type * dt; + struct mailmime_parameter * param; + clist * param_list; + + dt = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, NULL); + type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, dt, NUL); + param_list = clist_new(); + param = mailmime_parameter_new(strdup("charset"), strdup("iso-8859-1")); + clist_append(param_list, param); + + content = mailmime_content_new(type, strdup("plain"), param_list); + + /* do your things */ + + exit(EXIT_SUCCESS); +} + +void display_mime_content(struct mailmime_content * content_type) +{ + clistiter * cur; + + printf("type:\n"); + display_type(content_type->ct_type); + printf("\n"); + printf("subtype: %s\n", content_type->ct_subtype); + printf("\n"); + + for(cur = clist_begin(content_type->ct_parameters) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + display_mime_parameter(param); + printf("\n"); + } + printf("\n"); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-DISCRETE-TYPE" +>mailmime_discrete_type - MIME discrete type</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISCRETE_TYPE_ERROR, + MAILMIME_DISCRETE_TYPE_TEXT, + MAILMIME_DISCRETE_TYPE_IMAGE, + MAILMIME_DISCRETE_TYPE_AUDIO, + MAILMIME_DISCRETE_TYPE_VIDEO, + MAILMIME_DISCRETE_TYPE_APPLICATION, + MAILMIME_DISCRETE_TYPE_EXTENSION +}; + +struct mailmime_discrete_type { + int dt_type; + char * dt_extension; +}; + +struct mailmime_discrete_type * +mailmime_discrete_type_new(int dt_type, char * dt_extension); + +void mailmime_discrete_type_free(struct mailmime_discrete_type * + discrete_type); + </PRE +><P +> This is a MIME discrete type such as <B +CLASS="COMMAND" +>text</B +> or + <B +CLASS="COMMAND" +>image</B +>. This is also known as single part. This kind + of part does not have any child. + </P +><P +> <B +CLASS="COMMAND" +>dt_type</B +> is one of the given values : + <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_TEXT</B +> if part is text, + <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_IMAGE</B +> if part is an image, + <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_AUDIO</B +> if part is + audio data, + <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_VIDEO</B +> if part is video, + <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_APPLICATION</B +> if + part is application data or + <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_EXTENSION</B +> for other. + In the case of <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_EXTENSION</B +>, + <B +CLASS="COMMAND" +>dt_extension</B +> is filled in. + <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_ERROR</B +> is used internally. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_discrete_type_new()</B +> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_discrete_type_free()</B +> frees + memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1691" +></A +><P +><B +>Example 4-3. Creation and display of MIME discrete type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +/* standard type */ + +int main(int argc, char ** argv) +{ + struct mailmime_discrete_type * discrete_type; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, + NULL); + + /* do the things */ + + mailmime_discrete_type_free(discrete_type); +} + +/* extension */ + +int main(int argc, char ** argv) +{ + struct mailmime_discrete_type * discrete_type; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_EXTENSION, + strdup("my-type")); + + /* do the things */ + + mailmime_discrete_type_free(discrete_type); +} + +void display_mime_discrete_type(struct mailmime_discrete_type * discrete_type) +{ + switch (discrete_type->dt_type) { + case MAILMIME_DISCRETE_TYPE_TEXT: + printf("text\n"); + break; + case MAILMIME_DISCRETE_TYPE_IMAGE: + printf("image\n"); + break; + case MAILMIME_DISCRETE_TYPE_AUDIO: + printf("audio\n"); + break; + case MAILMIME_DISCRETE_TYPE_VIDEO: + printf("video\n"); + break; + case MAILMIME_DISCRETE_TYPE_APPLICATION: + printf("application\n"); + break; + case MAILMIME_DISCRETE_TYPE_EXTENSION: + printf("extension : %s\n", discrete_type->dt_extension); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELD" +>mailmime_field - MIME header field</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_FIELD_NONE, + MAILMIME_FIELD_TYPE, + MAILMIME_FIELD_TRANSFER_ENCODING, + MAILMIME_FIELD_ID, + MAILMIME_FIELD_DESCRIPTION, + MAILMIME_FIELD_VERSION, + MAILMIME_FIELD_DISPOSITION, + MAILMIME_FIELD_LANGUAGE, +}; + +struct mailmime_field { + int fld_type; + union { + struct mailmime_content * fld_content; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + struct mailmime_language * fld_language; + } fld_data; +}; + +struct mailmime_field * +mailmime_field_new(int fld_type, + struct mailmime_content * fld_content, + struct mailmime_mechanism * fld_encoding, + char * fld_id, + char * fld_description, + uint32_t fld_version, + struct mailmime_disposition * fld_disposition, + struct mailmime_language * fld_language); + +void mailmime_field_free(struct mailmime_field * field); + </PRE +><P +> This is a parsed MIME header field; + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fld_type</B +> is the type of MIME header field. The value can + be + <B +CLASS="COMMAND" +>MAILMIME_FIELD_TYPE</B +> + if field is <B +CLASS="COMMAND" +>Content-Type</B +>, + <B +CLASS="COMMAND" +>MAILMIME_FIELD_TRANSFER_ENCODING</B +> + if field is <B +CLASS="COMMAND" +>Content-Transfer-Encoding</B +>, + <B +CLASS="COMMAND" +>MAILMIME_FIELD_ID</B +> + if field is <B +CLASS="COMMAND" +>Content-ID</B +>, + <B +CLASS="COMMAND" +>MAILMIME_FIELD_DESCRIPTION</B +> + if field is <B +CLASS="COMMAND" +>Content-Description</B +>, + <B +CLASS="COMMAND" +>MAILMIME_FIELD_VERSION</B +> + if field is <B +CLASS="COMMAND" +>MIME-Version</B +>, + <B +CLASS="COMMAND" +>MAILMIME_FIELD_DISPOSITION</B +> + if field is <B +CLASS="COMMAND" +>Content-Disposition</B +> or + <B +CLASS="COMMAND" +>MAILMIME_FIELD_LANGUAGE</B +> + if field is <B +CLASS="COMMAND" +>Content-Language</B +>. + <B +CLASS="COMMAND" +>MAILMIME_FIELD_NONE</B +> is used internally. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_content</B +> is set in case of + <B +CLASS="COMMAND" +>Content-Type</B +>. + (see <A +HREF="#MAILMIME-CONTENT" +>the Section called <I +>mailmime_content - MIME content type (Content-Type)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_encoding</B +> is set in case of + <B +CLASS="COMMAND" +>Content-Transfer-Encoding</B +>. + (see <A +HREF="#MAILMIME-MECHANISM" +>the Section called <I +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_id</B +> is set in case of + <B +CLASS="COMMAND" +>Content-ID</B +>. This is a string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_description</B +> is set in case of + <B +CLASS="COMMAND" +>Content-Description</B +>. This is a string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_version</B +> is set in case of + <B +CLASS="COMMAND" +>MIME-Version</B +>. This is an integer built + using the following formula : + <B +CLASS="COMMAND" +>fld_version = major * 2^16 + minor</B +>. + Currenly MIME-Version is always <B +CLASS="COMMAND" +>1.0</B +>, this means that + fld_version will always be <B +CLASS="COMMAND" +>2^16</B +> (in C language, + this is <B +CLASS="COMMAND" +>1 << 16</B +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_disposition</B +> is set in case of + <B +CLASS="COMMAND" +>Content-Disposition</B +>. + (see <A +HREF="#MAILMIME-DISPOSITION" +>the Section called <I +>mailmime_disposition - MIME disposition information (Content-Disposition)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_language</B +> is set in case of + <B +CLASS="COMMAND" +>Content-Language</B +>. + (see <A +HREF="#MAILMIME-LANGUAGE" +>the Section called <I +>mailmime_language - Language of MIME part</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailmime_field_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_field_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1757" +></A +><P +><B +>Example 4-4. Creation and display of MIME header field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_field * field; + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL); + + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, encoding, NULL, NULL, 0, NULL, NULL); + + /* do the things */ + + mailmime_field_free(field); +} + +void display_mime_field(struct mailmime_field * field) +{ + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + printf("content-type:"); + display_mime_content(field->fld_data.fld_content); + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + printf("content-transfer-encoding:"); + display_mime_mechanism(field->fld_data.fld_encoding); + break; + case MAILMIME_FIELD_ID: + printf("content-id: %s\n", field->fld_data.fld_id); + break; + case MAILMIME_FIELD_DESCRIPTION: + printf("content-description: %s\n", field->fld_data.fld_description); + break; + case MAILMIME_FIELD_VERSION: + printf("mime-version: %i.%i\n", + field->version>> 16, field->fld_data.fld_version & 0xFFFF); + break; + case MAILMIME_FIELD_DISPOSITION: + printf("content-disposition:"); + display_mime_disposition(field->fld_data.fld_disposition); + break; + case MAILMIME_FIELD_LANGUAGE: + printf("content-language:"); + display_mime_language(field->fld_data.fld_language); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-MECHANISM" +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_mechanism { + int enc_type; + char * enc_token; +}; + +struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token); + +void mailmime_mechanism_free(struct mailmime_mechanism * mechanism); + </PRE +><P +> This is a MIME transfer encoding mechanism description. + </P +><P +> <B +CLASS="COMMAND" +>enc_type</B +> is an encoding type. The value of this field + can be + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_7BIT</B +> + if mechanism is <B +CLASS="COMMAND" +>7bit</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_8BIT</B +> + if mechanism is <B +CLASS="COMMAND" +>8bit</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BINARY</B +> + if mechanism is <B +CLASS="COMMAND" +>binary</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_QUOTED_PRINTABLE</B +> + if mechanism is <B +CLASS="COMMAND" +>quoted-printable</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BASE64</B +> + if mechanism is <B +CLASS="COMMAND" +>base64</B +> or + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_TOKEN</B +> for other. + In case of <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_TOKEN</B +>, + field <B +CLASS="COMMAND" +>enc_token</B +> is filled in. + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_ERROR</B +> is used internally. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_mechanism_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_mechanism_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1784" +></A +><P +><B +>Example 4-5. Creation and display of MIME transfer encoding mechanism</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_QUOTED_PRINTABLE, NULL); + + /* do the things */ + + mailmime_mechanism_free(encoding); +} + +int main(int argc, char ** argv) +{ + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_TOKEN, + strdup("uuencoding")); + + /* do the things */ + + mailmime_mechanism_free(encoding); +} + +void display_mime_mechanism(struct mailmime_mechanism * encoding) +{ + switch (encoding->enc_type) { + case MAILMIME_MECHANISM_7BIT: + printf("7bit\n"); + break; + case MAILMIME_MECHANISM_8BIT: + printf("8bit\n"); + break; + case MAILMIME_MECHANISM_BINARY: + printf("binary\n"); + break; + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + printf("quoted-printable\n"); + break; + case MAILMIME_MECHANISM_BASE64: + printf("base64\n"); + break; + case MAILMIME_MECHANISM_TOKEN: + printf("extension : %s\n", encoding->enc_token); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELDS" +>mailmime_fields - header fields</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_fields { + clist * fld_list; /* list of (struct mailmime_field *) */ +}; + +struct mailmime_fields * mailmime_fields_new(clist * fld_list); + +void mailmime_fields_free(struct mailmime_fields * fields); + </PRE +><P +> This is the header fields of a MIME part. + </P +><P +> <B +CLASS="COMMAND" +>fld_list</B +> is the list of the header fields. + Each element of the list is a <B +CLASS="COMMAND" +>mailmime_field</B +> + (See <A +HREF="#MAILMIME-FIELD" +>the Section called <I +>mailmime_field - MIME header field</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailmime_fields_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_fields_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1799" +></A +><P +><B +>Example 4-6. Creation and display of MIME fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_field * field; + struct mailmime_fields * fields; + clist * list; + struct mailmime_mechanism * encoding; + struct mailmime_disposition * disposition; + + list = clist_new(); + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL); + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, encoding, NULL, NULL, 0, NULL, NULL); + clist_append(list, field); + + field = mailmime_field_new(MAILMIME_FIELD_VERSION, + NULL, NULL, NULL, NULL, 1 << 16, NULL, NULL); + clist_append(list, field); + + /* look at the example in mailmime_disposition to see how to + build a mailmime_disposition */ + disposition = build_mime_disposition(); + field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION, + NULL, NULL, NULL, NULL, 0, disposition, NULL); + clist_append(list, field); + + fields = mailmime_fields_new(list); + + /* do the things */ + + mailmime_fields_free(fields); +} + +void display_mime_fields(struct mailmime_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + display_field(field); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-PARAMETER" +>mailmime_parameter - MIME type parameter</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>struct mailmime_parameter { + char * pa_name; + char * pa_value; +}; + </PRE +><P +> This is the MIME type parameter in + <B +CLASS="COMMAND" +>Content-Type</B +> MIME header + field. For example, this can be + <B +CLASS="COMMAND" +>charset="iso-8859-1"</B +>. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>pa_name</B +> is the name of the parameter, + for example : <B +CLASS="COMMAND" +>charset</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>pa_value</B +> is the value of the parameter, + for example : <B +CLASS="COMMAND" +>iso-8859-1</B +>. + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailmime_parameter_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_parameter_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1821" +></A +><P +><B +>Example 4-7. Creation and display of MIME type parameter</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_parameter * param; + + param = mailmime_parameter_new(strdup("charset"), strdup("iso-8859-1")); + + /* do the things */ + + mailmime_parameter_free(param); +} + +void display_mime_parameter(struct mailmime_parameter * param) +{ + printf("%s = %s\n", param->pa_name, param->pa_value); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-TYPE" +>mailmime_type - MIME main type</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_TYPE_ERROR, + MAILMIME_TYPE_DISCRETE_TYPE, + MAILMIME_TYPE_COMPOSITE_TYPE +}; + +struct mailmime_type { + int tp_type; + union { + struct mailmime_discrete_type * tp_discrete_type; + struct mailmime_composite_type * tp_composite_type; + } tp_data; +}; + +struct mailmime_type * +mailmime_type_new(int tp_type, + struct mailmime_discrete_type * tp_discrete_type, + struct mailmime_composite_type * tp_composite_type); + +void mailmime_type_free(struct mailmime_type * type); + </PRE +><P +> This is the MIME main type (no subtype, no parameter). + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>tp_type</B +>. The value of this field + is either <B +CLASS="COMMAND" +>MAILMIME_TYPE_DISCRETE_TYPE</B +> for MIME discrete type, + or <B +CLASS="COMMAND" +>MAILMIME_TYPE_COMPOSITE_TYPE</B +> for MIME composite type. + <B +CLASS="COMMAND" +>MAILMIME_TYPE_ERROR</B +> is used internally. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>tp_data.tp_discrete_type</B +> is set when <B +CLASS="COMMAND" +>tp_type</B +> + is <B +CLASS="COMMAND" +>MAILMIME_TYPE_DISCRETE_TYPE</B +> + (see <A +HREF="#MAILMIME-DISCRETE-TYPE" +>the Section called <I +>mailmime_discrete_type - MIME discrete type</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>tp_data.tp_composite_type</B +> is set when <B +CLASS="COMMAND" +>tp_type</B +> + is <B +CLASS="COMMAND" +>MAILMIME_TYPE_COMPOSITE_TYPE</B +> + (see <A +HREF="#MAILMIME-COMPOSITE-TYPE" +>the Section called <I +>mailmime_composite_type - Composite MIME type</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailmime_discrete_type_new()</B +> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_discrete_type_free()</B +> frees + memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1851" +></A +><P +><B +>Example 4-8. Creation and display of MIME main type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_type * type; + struct mailmime_discrete_type * discrete_type; + + discrete_type = + mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, NULL); + type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, discrete_type, NULL); + + /* do the things */ + + mailmime_type_free(type); +} + +int main(int argc, char ** argv) +{ + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, composite_type); + + /* do the things */ + + mailmime_type_free(type); +} + +void display_mime_type(struct mailmime_type * type) +{ + printf("mime type:\n"); + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + printf("discrete type:\n"); + display_mime_discrete_type(type->tp_data.tp_discrete_type); + break; + case MAILMIME_TYPE_COMPOSITE_TYPE: + printf("composite type:\n"); + display_mime_composite_type(type->tp_data.tp_composite_type); + break; + } + printf("\n"); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-LANGUAGE" +>mailmime_language - Language of MIME part</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_language { + clist * lg_list; /* atom (char *) */ +}; + +struct mailmime_language * mailmime_language_new(clist * lg_list); + +void mailmime_language_free(struct mailmime_language * lang); + </PRE +><P +> This is the language used in the MIME part. + </P +><P +> <B +CLASS="COMMAND" +>lg_list</B +> is the list of codes of languages used + in the MIME part. This is a list of strings. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_language_new()</B +> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_language_free()</B +> frees + memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1864" +></A +><P +><B +>Example 4-9. Creation and display of language of MIME part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_language * language; + clist * list; + + list = clist_new(); + + clist_append(list, strdup("fr")); + clist_append(list, strdup("en")); + + language = mailmime_language_new(list); + + /* do the things */ + + mailmime_language_free(language); +} + +void display_mime_language(struct mailmime_language * language) +{ + clistiter * cur; + + printf("languages: "); + for(cur = clist_begin(language->lg_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * name; + + name = clist_content(cur); + printf("%s ", name); + } + printf("\n"); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-DATA" +>mailmime_data - Content of MIME part</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_DATA_TEXT, + MAILMIME_DATA_FILE, +}; + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_data { + int dt_type; + int dt_encoding; + int dt_encoded; + union { + struct { + const char * dt_data; + size_t dt_length; + } dt_text; + char * dt_filename; + } dt_data; +}; + +struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, + int dt_encoded, const char * dt_data, size_t dt_length, + char * dt_filename); + +void mailmime_data_free(struct mailmime_data * mime_ </PRE +><P +> This is the content of MIME part, content of + preamble or content of epilogue. + </P +><P +> <B +CLASS="COMMAND" +>dt_type</B +> can be + <B +CLASS="COMMAND" +>MAILMIME_DATA_TEXT</B +> if + the content is a string in memory, + <B +CLASS="COMMAND" +>MAILMIME_DATA_FILE</B +> if the + content is in a file, + </P +><P +> <B +CLASS="COMMAND" +>dt_encoding</B +> is the encoding mechanism + of the part. The value of this field can be + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_7BIT</B +> if mechanism is + <B +CLASS="COMMAND" +>7bit</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_8BIT</B +> if mechanism is + <B +CLASS="COMMAND" +>8bit</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BINARY</B +> if mechanism is + <B +CLASS="COMMAND" +>binary</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_QUOTED_PRINTABLE</B +> if + mechanism is <B +CLASS="COMMAND" +>quoted-printable</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BASE64</B +> if mechanism is + <B +CLASS="COMMAND" +>base64</B +> or + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_TOKEN</B +> for other. If + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_TOKEN</B +>, the part will + be considered as binary. + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_ERROR</B +> is used internally. + </P +><P +> <B +CLASS="COMMAND" +>dt_encoded</B +> is set to 1 if the part is + already encoded with the mechanism given in + <B +CLASS="COMMAND" +>dt_encoding</B +>. It is set to 0 if the part + is already decoded or if it is necessary to encode that part + before rendering it. + </P +><P +> <B +CLASS="COMMAND" +>dt_data.dt_text.dt_data</B +> is a pointer to the + content of the part and <B +CLASS="COMMAND" +>dt_data.dt_text.dt_length</B +> + is the length of the data if <B +CLASS="COMMAND" +>dt_type</B +> is + <B +CLASS="COMMAND" +>MAILMIME_DATA_TEXT</B +>. + </P +><P +> <B +CLASS="COMMAND" +>dt_data.dt_filename</B +> is the name of the file if + <B +CLASS="COMMAND" +>dt_type</B +> is <B +CLASS="COMMAND" +>MAILMIME_DATA_FILE</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_data_new()</B +> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_data_free()</B +> frees + memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1906" +></A +><P +><B +>Example 4-10. Creation and display of MIME part content</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +/* build data with a string */ + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_BASE64, + 0, "foo bar", 7, NULL); + + /* do the things */ + + mailmime_data_free(data); +} + +/* build data with a file */ + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_BASE64, + 0, NULL, 0, strdup("foo.txt")); + + /* do the things */ + + mailmime_data_free(data); +} + +void display_mime_data(struct mailmime_data * data) +{ + switch (data->dt_encoding) { + case MAILMIME_MECHANISM_7BIT: + printf("7bit\n"); + break; + case MAILMIME_MECHANISM_8BIT: + printf("8bit\n"); + break; + case MAILMIME_MECHANISM_BINARY: + printf("binary\n"); + break; + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + printf("quoted-printable\n"); + break; + case MAILMIME_MECHANISM_BASE64: + printf("base64\n"); + break; + case MAILMIME_MECHANISM_TOKEN: + printf("other\n"); + break; + } + + if (data->dt_encoded) + printf("already encoded\n"); + else + printf("not encoded\n"); + + switch (data->dt_type) { + MAILMIME_DATA_TEXT: + printf("data : %p %i\n", data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length); + break; + MAILMIME_DATA_FILE, + printf("data (file) : %s\n", data->dt_data.dt_filename); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME" +>mailmime - MIME part</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_NONE, + MAILMIME_SINGLE, + MAILMIME_MULTIPLE, + MAILMIME_MESSAGE, +}; + +struct mailmime { + /* parent information */ + int mm_parent_type; + struct mailmime * mm_parent; + clistiter * mm_multipart_pos; + + int mm_type; + const char * mm_mime_start; + size_t mm_length; + + struct mailmime_fields * mm_mime_fields; + struct mailmime_content * mm_content_type; + + struct mailmime_data * mm_body; + union { + /* single part */ + struct mailmime_data * mm_single; /* XXX - was body */ + + /* multi-part */ + struct { + struct mailmime_data * mm_preamble; + struct mailmime_data * mm_epilogue; + clist * mm_mp_list; + } mm_multipart; + + /* message */ + struct { + struct mailimf_fields * mm_fields; + struct mailmime * mm_msg_mime; + } mm_message; + + } mm_data; +}; + +struct mailmime * mailmime_new(int mm_type, + const char * mm_mime_start, size_t mm_length, + struct mailmime_fields * mm_mime_fields, + struct mailmime_content * mm_content_type, + struct mailmime_data * mm_body, + struct mailmime_data * mm_preamble, + struct mailmime_data * mm_epilogue, + clist * mm_mp_list, + struct mailimf_fields * mm_fields, + struct mailmime * mm_msg_mime); + +void mailmime_free(struct mailmime * mime); + </PRE +><P +> This describes the MIME structure of a message or a subpart + of a message. + </P +><DIV +CLASS="SECT3" +><HR><H4 +CLASS="SECT3" +><A +NAME="AEN1913" +>common</A +></H4 +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>mm_parent_type</B +>. MIME part type can be + single part, multipart or message part. This describes the MIME part + type of the parent. The value can be + <B +CLASS="COMMAND" +>MAILMIME_NONE</B +> if there is no parent part, + <B +CLASS="COMMAND" +>MAILMIME_SINGLE</B +> if parent is a single part, + <B +CLASS="COMMAND" +>MAILMIME_MULTIPLE</B +> if parent is a multipart, + <B +CLASS="COMMAND" +>MAILMIME_MESSAGE</B +> if parent is a mesage part. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_parent</B +> is the parent MIME structure. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_multipart_pos</B +>. In the case the parent + is a multipart. This is the position in the list of children + of the parent. This position is given by a + <B +CLASS="COMMAND" +>clisiter *</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_type</B +>. This describes the MIME part type + of this part. The value can be + <B +CLASS="COMMAND" +>MAILMIME_SINGLE</B +> if this is a single part, + <B +CLASS="COMMAND" +>MAILMIME_MULTIPLE</B +> if this is a multipart, + <B +CLASS="COMMAND" +>MAILMIME_MESSAGE</B +> if this is a mesage part. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_mime_start</B +>. This is used mostly internally. + This gives the beginning of the header of the MIME part, when this + is parsed from a string in memory. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_length</B +>. This gives the length of the MIME part, + including the MIME header fields. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_mime_fields</B +> is the list of parsed MIME headers + of this part. <B +CLASS="COMMAND" +>Content-Type</B +> must be excluded and stored + in <B +CLASS="COMMAND" +>mm_content_type</B +> instead + (see <A +HREF="#MAILMIME-FIELDS" +>the Section called <I +>mailmime_fields - header fields</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_content_type</B +> is the parsed + <B +CLASS="COMMAND" +>Content-Type</B +> field + (see <A +HREF="#MAILMIME-CONTENT" +>the Section called <I +>mailmime_content - MIME content type (Content-Type)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_body</B +> is the content of the MIME part + (excluding MIME header), when it is parsed from a string + in memory + (see <A +HREF="#MAILMIME-DATA" +>the Section called <I +>mailmime_data - Content of MIME part</I +></A +>). + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT3" +><HR><H4 +CLASS="SECT3" +><A +NAME="AEN1957" +>single part</A +></H4 +><P +></P +><UL +><LI +><P +> When the part is a single part (<B +CLASS="COMMAND" +>mm_type</B +> + is <B +CLASS="COMMAND" +>MAILMIME_SINGLE</B +>). The following fields + are valid. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_data.mm_single</B +> is the content of the + MIME part (excluding MIME header), when it is parsed from a string + in memory. This must have the same + value as <B +CLASS="COMMAND" +>mm_body</B +> when it is set + (see <A +HREF="#MAILMIME-DATA" +>the Section called <I +>mailmime_data - Content of MIME part</I +></A +>). + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT3" +><HR><H4 +CLASS="SECT3" +><A +NAME="AEN1969" +>multipart</A +></H4 +><P +></P +><UL +><LI +><P +> When the part is a multipart (<B +CLASS="COMMAND" +>mm_type</B +> + is <B +CLASS="COMMAND" +>MAILMIME_MULTIPLE</B +>). The following fields + are valid. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_data.mm_multipart.mm_preamble</B +> + is the content of the preamble of the multipart + (see <A +HREF="#MAILMIME-DATA" +>the Section called <I +>mailmime_data - Content of MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_data.mm_multipart.mm_epilogue</B +> + is the content of the epilogue of the multipart + (see <A +HREF="#MAILMIME-DATA" +>the Section called <I +>mailmime_data - Content of MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_data.mm_multipart.mm_mp_list</B +> + is the list of sub parts + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT3" +><HR><H4 +CLASS="SECT3" +><A +NAME="AEN1987" +>message part</A +></H4 +><P +></P +><UL +><LI +><P +> When the part is a message (<B +CLASS="COMMAND" +>mm_type</B +> + is <B +CLASS="COMMAND" +>MAILMIME_MESSAGE</B +>). The following fields + are valid. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_data.mm_message.mm_fields</B +> is the list of + the header fields of the message + (see <A +HREF="#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +> in Chapter 3</A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_data.mm_message.mm_msg_mime</B +> is + the subpart + of the message part. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT3" +><HR><H4 +CLASS="SECT3" +><A +NAME="AEN2001" +>constructor and destructor</A +></H4 +><P +> <B +CLASS="COMMAND" +>mailmime_new()</B +> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_free()</B +> frees + memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2007" +></A +><P +><B +>Example 4-11. Creation and display of MIME part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +/* build one single MIME part */ + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + struct mailmime_data * body; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + /* look at the example in mailmime_content to see how to + build a mailmime_content */ + content_type = build_mime_content(); + + body = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + "foo", 3, NULL); + + mime = mailmime_new(MAILMIME_SINGLE, + NULL, 0, fields, mime_fields, content_type, + body, NULL, NULL, NULL, NULL, NULL); + + /* do the things */ + + mailmime_free(mime); +} + +/* build one single MIME part */ + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + char * str; + struct mailmime_data * body; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + /* look at the example in mailmime_content to see how to + build a mailmime_content */ + content_type = build_mime_content(); + + str = malloc(4); + strcpy(str, "foo"); + + body = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + str, 3, NULL); + + mime = mailmime_new(MAILMIME_SINGLE, + NULL, 0, fields, mime_fields, content_type, + body, NULL, NULL, NULL, NULL, NULL); + + /* do the things */ + + mailmime_free(mime); + free(str); +} + +/* build a MIME part with a sub-message */ + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + char * str; + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, + composite_type); + content_type = mailmime_content_new(type, strdup("rfc2822"), NULL); + + /* build_mime_message() is a function that will build a mime message part */ + sub_mime = build_mime_message(); + + mime = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, fields, mime_fields, content_type, + NULL, NULL, NULL, NULL, sub_mime, NULL); + + /* do the things */ + + mailmime_free(mime); +} + +/* build a MIME part with a sub-message (given by a string) */ + + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + char * str; + struct mailmime_data * msg_content; + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, + composite_type); + content_type = mailmime_content_new(type, strdup("rfc2822"), NULL); + + str = malloc(sizeof(SUB_MESSAGE)); + strcpy(str, SUB_MESSAGE); + + msg_content = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + str, sizeof(SUB_MESSAGE), NULL); + + mime = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, fields, mime_fields, content_type, + NULL, NULL, NULL, NULL, NULL, msg_content); + + /* do the things */ + + mailmime_free(mime); + free(str); +} + +/* build a multipart message */ + + + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + struct mailmime_data * body; + struct mailmime_data * preamble; + struct mailmime_data * epilogue; + clist * list; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, + composite_type); + content_type = mailmime_content_new(type, strdup("mixed"), NULL); + + list = clist_new(); + /* build_mime_message() is a function that will build a mime message part */ + sub_mime = build_mime_message(); + clist_append(list, sub_mime); + sub_mime = build_mime_message(); + clist_append(list, sub_mime); + + preamble = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + PREAMBLE, sizeof(PREAMBLE), NULL); + + epilogue = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + EPILOGUE, sizeof(EPILOGUE), NULL); + + mime = mailmime_new(MAILMIME_SINGLE, + NULL, 0, fields, mime_fields, content_type, + NULL, preamble, epilogue, list, NULL, NULL); + + /* do the things */ + + mailmime_free(mime); +} + +/* display mime part info */ + +void display_mime(struct mailmime * mime) +{ + clistiter * cur; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + printf("single part\n"); + break; + case MAILMIME_MULTIPLE: + printf("multipart\n"); + break; + case MAILMIME_MESSAGE: + printf("message\n"); + break; + } + + printf("part : %p, length : %i\n", + mime->mm_mime_start, mime->mm_length); + printf("\n"); + + if (mime->mm_mime_fields != NULL) { + printf("MIME headers :\n"); + display_mime_fields(mime->mm_mime_fields); + printf("\n"); + } + + printf("content type :\n"); + display_content(mime->mm_content_type); + printf("\n"); + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + display_mime_data(mime->mm_data.mm_single); + break; + + case MAILMIME_MULTIPLE: + if (mime->mm_data.mm_multipart.mm_preamble) { + printf("preamble :\n"); + display_mime_data(mime->mm_data.mm_multipart.mm_preamble); + printf("\n"); + } + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + display_mime(clist_content(cur)); + } + + if (mime->mm_data.mm_multipart.mm_epilogue) { + printf("epilogue :\n"); + display_mime_data(mime->mm_data.mm_multipart.mm_epilogue); + printf("\n"); + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_fields) { + printf("headers :\n"); + display_field(mime->mm_data.mm_message.mm_msg_fields); + printf("\n"); + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + printf("sub message %p :\n", + mime->mm_data.mm_message.mm_msg_mime); + display_mime(mime->mm_data.mm_message.mm_msg_mime); + printf("end of sub message %p\n", + mime->mm_data.mm_message.mm_msg_mime); + } + break; + } +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-DISPOSITION" +>mailmime_disposition - MIME disposition information (Content-Disposition)</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_disposition { + struct mailmime_disposition_type * dsp_type; + clist * dsp_parms; /* struct mailmime_disposition_parm */ +}; + </PRE +><P +> This is the parsed <B +CLASS="COMMAND" +>Content-Disposition</B +> + header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>dsp_type</B +> is the type of disposition + (see <A +HREF="#MAILMIME-DISPOSITION-TYPE" +>the Section called <I +>mailmime_disposition_type - Type of MIME disposition</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dsp_parms</B +> is the list of parameters + of <B +CLASS="COMMAND" +>Content-Disposition</B +> header field. + Each element is of type <B +CLASS="COMMAND" +>mailmime_disposition_parm</B +> + (see <A +HREF="#MAILMIME-DISPOSITION-PARM" +>the Section called <I +>mailmime_disposition_parm - MIME disposition parameter</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2026" +></A +><P +><B +>Example 4-12. Creation and display of MIME disposition information</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_disposition * disposition; + struct mailmime_disposition_type * disposition_type; + clist * disposition_parms; + struct mailmime_disposition_parm * param; + + disposition_type = + mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, NULL); + + disposition_parms = clist_new(); + param = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME, + strdup("foo.txt"), NULL, + NULL, NULL, -1, NULL); + clist_append(disposition_parms, param); + + disposition = mailmime_disposition_new(disposition_type, disposition_parms); + + /* do the things */ + + mailmime_disposition_free(disposition); +} + +void display_mime_disposition(struct mailmime_disposition * disposition) +{ + clistiter * cur; + + printf("disposition type:\n"); + display_mailmime_disposition_type(disposition->dsp_type); + printf("\n"); + printf("disposition parameters:\n"); + for(cur = clist_begin(disposition->dsp_parms) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parm * param; + + param = clist_content(cur); + display_mime_disposition_parm(param); + } + printf("\n"); +} + + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-DISPOSITION-TYPE" +>mailmime_disposition_type - Type of MIME disposition</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition_type { + int dsp_type; + char * dsp_extension; +}; + </PRE +><P +> This is the type of MIME disposition. + Parsed <B +CLASS="COMMAND" +>Content-Disposition</B +> field without + parameters. + </P +><P +> <B +CLASS="COMMAND" +>dsp_type</B +> is the type of disposition. + The value can be + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_INLINE</B +> + if MIME disposition is inline, + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_ATTACHMENT</B +> + if MIME disposition is attachment, + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_EXTENSION</B +> + for other. In this case, <B +CLASS="COMMAND" +>dsp_extension</B +> must be + set. + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_ERROR</B +> is used internally. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2041" +></A +><P +><B +>Example 4-13. Creation and display of MIME disposition type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +/* standard disposition type */ + +int main(int argc, char ** argv) +{ + struct mailmime_disposition_type * disposition_type; + + disposition_type = + mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, NULL); + + /* do the things */ + + mailmime_disposition_type_free(disposition_type); +} + +/* disposition type extension */ + +int main(int argc, char ** argv) +{ + struct mailmime_disposition_type * disposition_type; + + disposition_type = + mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_EXTENSION, + strdup("mydisposition")); + + /* do the things */ + + mailmime_disposition_type_free(disposition_type); +} + +void display_mime_disposition_type(struct mailmime_disposition_type * disposition_type) +{ + switch (disposition->dsp_type) { + case MAILMIME_DISPOSITION_TYPE_INLINE: + printf("inline\n"); + break; + case MAILMIME_DISPOSITION_TYPE_ATTACHMENT: + printf("attachment\n"); + break; + case MAILMIME_DISPOSITION_TYPE_EXTENSION: + printf("extension : %s\n", disposition_type->dsp_extension); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-DISPOSITION-PARM" +>mailmime_disposition_parm - MIME disposition parameter</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISPOSITION_PARM_FILENAME, + MAILMIME_DISPOSITION_PARM_CREATION_DATE, + MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, + MAILMIME_DISPOSITION_PARM_READ_DATE, + MAILMIME_DISPOSITION_PARM_SIZE, + MAILMIME_DISPOSITION_PARM_PARAMETER +}; + +struct mailmime_disposition_parm { + int pa_type; + union { + char * pa_filename; + char * pa_creation_date; + char * pa_modification_date; + char * pa_read_date; + size_t pa_size; + struct mailmime_parameter * pa_parameter; + } pa_data; +}; + </PRE +><P +> This is a parameter of MIME disposition information. For + example, this can be + <B +CLASS="COMMAND" +>filename="foo.jpg"</B +>. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>pa_type</B +> is the type of + disposition. The value can be + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_FILENAME</B +> + for a filename parameter, + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_CREATION_DATE</B +> + for a creation date parameter, + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE</B +> + for a modification date parameter, + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_READ_DATE</B +> + for a last read date parameter, + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_SIZE</B +> + for a file size parameter or + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_PARAMETER</B +> + for other parameters. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>pa_data.pa_filename</B +> is the filename + parameter when <B +CLASS="COMMAND" +>pa_type</B +> is + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_FILENAME</B +> + This is a string containing the name of the + file. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>pa_data.pa_creation_date</B +> is the + creation date parameter when <B +CLASS="COMMAND" +>pa_type</B +> is + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_CREATION_DATE</B +>. + This is a string containing the formatted creation date. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>pa_data.pa_modification_date</B +> is the + modification date parameter when <B +CLASS="COMMAND" +>pa_type</B +> is + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE</B +>. + This is a string containing the formatted modification date. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>pa_data.pa_read_date</B +> is the + last read date parameter when <B +CLASS="COMMAND" +>pa_type</B +> is + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_READ_DATE</B +>. + This is a string containing the formatted last read date. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>pa_data.pa_size</B +> is the size + parameter when <B +CLASS="COMMAND" +>pa_type</B +> is + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_SIZE</B +>. + This gives the size of the file. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>pa_data.pa_parameter</B +> is the + name and the value of the parameter when + <B +CLASS="COMMAND" +>pa_type</B +> is + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_PARAMETER</B +> + (see <A +HREF="#MAILMIME-PARAMETER" +>the Section called <I +>mailmime_parameter - MIME type parameter</I +></A +>) + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2090" +></A +><P +><B +>Example 4-14. Creation and display of MIME disposition + parameter</B +></P +><PRE +CLASS="PROGRAMLISTING" +>int main(int argc, char ** argv) +{ + struct mailmime_disposition_parm * param; + + disposition_parms = clist_new(); + param = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME, + strdup("foo.txt"), NULL, + NULL, NULL, -1, NULL); + /* do the things */ + + mailmime_disposition_parm_free(param); +} + +void display_mime_dsp_parm(struct mailmime_disposition_parm * param) +{ + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + printf("filename: %s\n", param->pa_data.pa_filename); + break; + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + printf("creation date: %s\n", param->pa_data.pa_creation_date); + break; + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + printf("modification date: %s\n", param->pa_data.pa_modification_date); + break; + case MAILMIME_DISPOSITION_PARM_READ_DATE: + printf("read date: %s\n", param->pa_data.pa_read_date); + break; + case MAILMIME_DISPOSITION_PARM_SIZE: + printf("size: %lu\n", (unsigned long) param->pa_data.pa_size); + break; + case MAILMIME_DISPOSITION_PARM_PARAMETER: + printf("MIME disposition param:\n"); + display_mime_parameter(param->pa_data.pa_parameter); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-SINGLE-FIELDS" +>mailmime_single_fields - MIME headers</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_single_fields { + struct mailmime_content * fld_content; + char * fld_content_charset; + char * fld_content_boundary; + char * fld_content_name; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + char * fld_disposition_filename; + char * fld_disposition_creation_date; + char * fld_disposition_modification_date; + char * fld_disposition_read_date; + size_t fld_disposition_size; + struct mailmime_language * fld_language; +}; + +struct mailmime_single_fields * +mailmime_single_fields_new(struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +void mailmime_single_fields_free(struct mailmime_single_fields * + single_fields); + +void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, + struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_fields</B +> (see <A +HREF="#MAILMIME-FIELDS" +>the Section called <I +>mailmime_fields - header fields</I +></A +>) is the native structure + that MIME module will use, this module will provide an easier + structure to use when + parsing fields. <B +CLASS="COMMAND" +>mailmime_single_fields</B +> is + an easier structure to get parsed fields, rather than + iteration over the list of fields. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fld_content</B +> is the MIME content type + (see <A +HREF="#MAILMIME-CONTENT" +>the Section called <I +>mailmime_content - MIME content type (Content-Type)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_content_charset</B +> is the value + of the MIME type parameter <B +CLASS="COMMAND" +>charset</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_content_boundary</B +> is the value + of the MIME type parameter <B +CLASS="COMMAND" +>boundary</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_content_name</B +> is the value + of the MIME type parameter <B +CLASS="COMMAND" +>name</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_encoding</B +> is the MIME encoding + mechanism used + (see <A +HREF="#MAILMIME-MECHANISM" +>the Section called <I +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_id</B +> is the content of the field + <B +CLASS="COMMAND" +>Content-ID</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_description</B +> is the content of the field + <B +CLASS="COMMAND" +>Content-Description</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_version</B +> is the version of MIME + in use. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_disposition</B +> is the MIME + disposition information + (see <A +HREF="#MAILMIME-DISPOSITION" +>the Section called <I +>mailmime_disposition - MIME disposition information (Content-Disposition)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_disposition_filename</B +> is + the <B +CLASS="COMMAND" +>filename</B +> parameter of the + MIME disposition information. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_disposition_creation_date</B +> is + the <B +CLASS="COMMAND" +>creation-date</B +> parameter of the + MIME disposition information. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_disposition_modification_date</B +> is + the <B +CLASS="COMMAND" +>modification-date</B +> parameter of the + MIME disposition information. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_disposition_read_date</B +> is + the <B +CLASS="COMMAND" +>read-date</B +> parameter of the + MIME disposition information. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_disposition_size</B +> is + the <B +CLASS="COMMAND" +>size</B +> parameter of the + MIME disposition information. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_language</B +> is the language + of the MIME part + (see <A +HREF="#MAILMIME-LANGUAGE" +>the Section called <I +>mailmime_language - Language of MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>single_fields</B +> is the structure to fill. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_fields</B +> is the MIME fields list to + use to fill the <B +CLASS="COMMAND" +>single_fields</B +>. + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailmime_single_fields_new()</B +> creates and + initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> be freed if the + object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_single_fields_free()</B +> frees + memory used by the structure and + substructures will <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> be + released. They should be released by + the application. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_single_fields_init()</B +> will + initialize fill the data structure, using + the given argument (<B +CLASS="COMMAND" +>fld_fields</B +> and + <B +CLASS="COMMAND" +>fld_content</B +>). The interesting fields will + be filled into single_fields. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2177" +></A +><P +><B +>Example 4-15. Creation and display of single fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_single_fields * single_fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + /* look at the example in mailmime_content to see how to + build a mailmime_content */ + content_type = build_mime_content(); + + single_fields = mailmime_single_fields_new(mime_fields, content_type); + + /* do the things */ + + mailmime_single_fields_free(single_fields); + mailmime_fields_free(mime_fields); +} + +void display_mime_single_fields(struct mailmime_single_fields * single_fields) +{ + if (single_fields->fld_content != NULL) { + printf("content type:\n"); + display_mime_content(single_fields->fld_content); + printf("\n"); + } + if (single_fields->fld_content_charset != NULL) { + printf("content type charset: %s\n", + single_fields->fld_content_charset); + printf("\n"); + } + if (single_fields->fld_content_boundary != NULL) { + printf("content type boundary: %s\n", + single_fields->fld_content_boundary); + printf("\n"); + } + if (single_fields->content_name != NULL) { + printf("content type name: %s\n", single_fields->content_name); + printf("\n"); + } + if (single_fields->fld_encoding != NULL) { + printf("content transfer encoding:\n"); + display_mime_mechanism(single_fields->fld_encoding); + printf("\n"); + } + if (single_fields->fld_id != NULL) { + printf("content id: %s\n", single_fields->fld_id); + printf("\n"); + } + if (single_fields->fld_description != NULL) { + printf("content description: %s\n", single_fields->fld_description); + printf("\n"); + } + if (single_fields->fld_version != 0) { + printf("mime version: %i.%i\n", + single_fields->fld_version>> 16, + single_fields->fld_version & 0xFFFF); + printf("\n"); + } + if (single_fields->fld_disposition != NULL) { + printf("content disposition:\n"); + display_mime_disposition(single_fields->fld_disposition); + printf("\n"); + } + if (single_fields->fld_disposition_filename != NULL) { + printf("content disposition filename: %s\n", + single_fields->fld_disposition_filename); + printf("\n"); + } + if (single_fields->fld_disposition_creation_date != NULL) { + printf("content disposition creation date: %s\n", + single_fields->fld_disposition_creation_date); + printf("\n"); + } + if (single_fields->fld_disposition_modification_date != NULL) { + printf("content disposition modification date: %s\n", + single_fields->fld_disposition_modification_date); + printf("\n"); + } + if (single_fields->fld_disposition_read_date != NULL) { + printf("content disposition read date: %s\n", + single_fields->fld_disposition_read_date; + printf("\n"); + } + if (single_fields->fld_disposition_size != (size_t) -1) { + printf("content disposition size : %i\n", + single_fields->fld_disposition_size); + printf("\n"); + } + if (single_fields->language != NULL) { + printf("content language:\n"); + display_mime_language(single_fields->fld_language); + printf("\n"); + } +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN2180" +>Parser functions</A +></H2 +><DIV +CLASS="SECT2" +><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-CONTENT-PARSE" +>mailmime_content_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_content_parse(const char * message, size_t length, + size_t * index, + struct mailmime_content ** result); + </PRE +><P +> This function will parse the content of a + <B +CLASS="COMMAND" +>Content-Type</B +> header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME content type. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILMIME-CONTENT" +>the Section called <I +>mailmime_content - MIME content type (Content-Type)</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2203" +></A +><P +><B +>Example 4-16. Parsing MIME content type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Type") == 0) { + struct mailmime_content * content_type; + size_t current_index; + + current_index = 0; + r = mailmime_content_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &content_type); + if (r == MAILIMF_NO_ERROR) { + display_mime_content(content_type); + /* do the things */ + status = EXIT_SUCCESS; + mailmime_content_free(content_type); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-DESCRIPTION-PARSE" +>mailmime_description_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include >libetpan/libetpan.h< + +int mailmime_description_parse(const char * message, size_t length, + size_t * index, + char ** result); + </PRE +><P +> This will parse the content of + <B +CLASS="COMMAND" +>Content-Description</B +> MIME header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME content description. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +>. + The result string must be freed with + <B +CLASS="COMMAND" +>free()</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2227" +></A +><P +><B +>Example 4-17. Parsing MIME description</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Description") == 0) { + char * description; + size_t current_index; + + current_index = 0; + r = mailmime_description_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &description); + if (r == MAILIMF_NO_ERROR) { + printf("%s\n", description); + /* do the things */ + status = EXIT_SUCCESS; + free(description); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-ENCODING-PARSE" +>mailmime_encoding_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include >libetpan/libetpan.h< + +int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result); + </PRE +><P +> This function will parse the content of + <B +CLASS="COMMAND" +>Content-Transfer-Encoding</B +> header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME encoding mechanism. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILMIME-MECHANISM" +>the Section called <I +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2251" +></A +><P +><B +>Example 4-18. parsing MIME encoding mechanism</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Transfer-Encoding") == 0) { + struct mailmime_content * encoding; + size_t current_index; + + current_index = 0; + r = mailmime_encoding_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &encoding); + if (r == MAILIMF_NO_ERROR) { + display_mime_mechanism(encoding); + /* do the things */ + status = EXIT_SUCCESS; + mailmime_mechanism_free(encoding); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELD-PARSE" +>mailmime_field_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int +mailmime_field_parse(struct mailimf_optional_field * field, + struct mailmime_field ** result); + </PRE +><P +> This function will parse a MIME header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>field</B +> is a non-parsed field + (see <A +HREF="#MAILIMF-OPTIONAL-FIELD" +>the Section called <I +>mailimf_optional_field - non-standard header</I +> in Chapter 3</A +>). + </P +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILMIME-FIELD" +>the Section called <I +>mailmime_field - MIME header field</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2267" +></A +><P +><B +>Example 4-19. parsing MIME header field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + r = mailmime_field_parse(field->fld_data.fld_optional_field, + &mime_fields); + if (r == MAILIMF_NO_ERROR) { + display_mime_field(mime_field); + mailmime_field_free(mime_field); + status = EXIT_SUCCESS; + } + } + } + + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-ID-PARSE" +>mailmime_id_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include >libetpan/libetpan.h< + +int mailmime_id_parse(const char * message, size_t length, + size_t * index, char ** result); + </PRE +><P +> This will parse the content of + <B +CLASS="COMMAND" +>Content-ID</B +> MIME header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME content identifier. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +>. + The result string must be freed with + <B +CLASS="COMMAND" +>free()</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2291" +></A +><P +><B +>Example 4-20. Parsing MIME content identifier</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-ID") == 0) { + char * id; + size_t current_index; + + current_index = 0; + r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &id); + if (r == MAILIMF_NO_ERROR) { + printf("%s\n", id); + /* do the things */ + status = EXIT_SUCCESS; + free(id); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELDS-PARSE" +>mailmime_fields_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int +mailmime_fields_parse(struct mailimf_fields * fields, + struct mailmime_fields ** result); + </PRE +><P +> This function will parse a MIME header fields. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fields</B +> is a list of RFC 2822 fields + (see <A +HREF="#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +> in Chapter 3</A +>). + </P +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILMIME-FIELDS" +>the Section called <I +>mailmime_fields - header fields</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2307" +></A +><P +><B +>Example 4-21. parsing MIME header fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + struct mailmime_fields * mime_fields; + + r = mailmime_fields_parse(f, &mime_fields); + if (r == MAILIMF_NO_ERROR) { + display_mime_fields(mime_fields); + mailmime_fields_free(mime_fields); + status = EXIT_SUCCESS; + } + + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-VERSION-PARSE" +>mailmime_version_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_version_parse(const char * message, size_t length, + size_t * index, + uint32_t * result); + </PRE +><P +> This will parse the content of + <B +CLASS="COMMAND" +>MIME-Version</B +> MIME header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME version. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILMIME-FIELD" +>the Section called <I +>mailmime_field - MIME header field</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2331" +></A +><P +><B +>Example 4-22. parsing MIME version</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "MIME-Version") == 0) { + uint32_t version; + size_t current_index; + + current_index = 0; + r = mailmime_version_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &version); + if (r == MAILIMF_NO_ERROR) { + printf("%i.%i\n", version >> 16, version & 0xFFFF); + /* do the things */ + status = EXIT_SUCCESS; + free(description); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-PARAMETER-PARSE" +>mailmime_parameter_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_parameter_parse(const char * message, size_t length, + size_t * index, + struct mailmime_parameter ** result); + </PRE +><P +> This will parse a MIME parameter (parameter of + <B +CLASS="COMMAND" +>Content-Type</B +> or parameter of + <B +CLASS="COMMAND" +>Content-Disposition</B +>). + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME parameter. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILMIME-PARAMETER" +>the Section called <I +>mailmime_parameter - MIME type parameter</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2356" +></A +><P +><B +>Example 4-23. parsing a MIME parameter</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define PARAM_STR "foo=bar" + +int main(int argc, char ** argv) +{ + int fd; + int r; + size_t current_index; + struct mailmime_parameter * param; + int status; + + status = EXIT_FAILURE; + + current_index = 0; + r = mailmime_parameter_parse(PARAM_STR, sizeof(PARAM_STR) - 1, + ¤t_index, ¶m); + if (r == MAILIMF_NO_ERROR) { + display_mime_parameter(param); + /* do the things */ + mailmime_parameter_free(param); + status = EXIT_SUCCESS; + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-LANGUAGE-PARSE" +>mailmime_language_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_language_parse(const char * message, size_t length, + size_t * index, + struct mailmime_language ** result); + </PRE +><P +> This function will parse the content of a + <B +CLASS="COMMAND" +>Content-Language</B +> header. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME content language. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILMIME-LANGUAGE" +>the Section called <I +>mailmime_language - Language of MIME part</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2380" +></A +><P +><B +>Example 4-24. Parsing the MIME content langage</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Language") == 0) { + struct mailmime_language * lang; + size_t current_index; + + current_index = 0; + r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &lang); + if (r == MAILIMF_NO_ERROR) { + display_mime_language(lang); + /* do the things */ + status = EXIT_SUCCESS; + free(id); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-DISPOSITION-PARSE" +>mailmime_disposition_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_disposition_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition ** result); + </PRE +><P +> This function will parse the content of a + <B +CLASS="COMMAND" +>Content-Disposition</B +> MIME header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME content disposition. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILMIME-DISPOSITION" +>the Section called <I +>mailmime_disposition - MIME disposition information (Content-Disposition)</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2404" +></A +><P +><B +>Example 4-25. Parsing the MIME content disposition</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Disposition") == 0) { + struct mailmime_disposition * dsp; + size_t current_index; + + current_index = 0; + r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &dsp); + if (r == MAILIMF_NO_ERROR) { + display_mime_disposition(dsp); + /* do the things */ + status = EXIT_SUCCESS; + free(id); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-DISPOSITION-TYPE-PARSE" +>mailmime_disposition_type_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int +mailmime_disposition_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_type ** + result); + </PRE +><P +> This function will parse the type of MIME content + disposition. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME content disposition type. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILMIME-DISPOSITION-TYPE" +>the Section called <I +>mailmime_disposition_type - Type of MIME disposition</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2427" +></A +><P +><B +>Example 4-26. parsing a MIME content disposition type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define DSP_TYPE_STR "attachment" + +int main(int argc, char ** argv) +{ + int fd; + int r; + size_t current_index; + struct mailmime_disposition_type * dsp_type; + int status; + + status = EXIT_FAILURE; + + current_index = 0; + r = mailmime_disposition_type_parse(DSP_TYPE_STR, sizeof(DSP_TYPE_STR) - 1, + ¤t_index, &dsp_type); + if (r == MAILIMF_NO_ERROR) { + display_mime_disposition_type(dsp_type); + /* do the things */ + mailmime_disposition_type_free(dsp_type); + status = EXIT_SUCCESS; + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-ENCODED-PHRASE-PARSE" +>mailmime_encoded_phrase_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_encoded_phrase_parse(const char * default_fromcode, + const char * message, size_t length, + size_t * index, const char * tocode, + char ** result); + </PRE +><P +> This function will decode a MIME encoded header string, + encoded with RFC 2047. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>default_fromcode</B +> is the default + code to use for parts of string that are not marked + with charset. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is the string to decode. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>tocode</B +> is the destination charset + for decoding. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2455" +></A +><P +><B +>Example 4-27. decoding a MIME encoded header string</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define TEST_STRING "=?iso-8859-1?ab?= =?iso-8859-15?cd?=" + +int main(int argc, char ** argv) +{ + size_t cur_token; + char * decoded_subject; + + cur_token = 0; + mailmime_encoded_phrase_parse("iso-8859-1", + TEST_STRING, sizeof(TEST_STRING), + &cur_token, "iso-8859-1", &decoded_subject); + + printf("%s\n", decoded_subject); + + /* do the things */ + + free(decoded_subject); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-PARSE" +>mailmime_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_parse(const char * message, size_t length, + size_t * index, struct mailmime ** result); + </PRE +><P +> This will parse a MIME message. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2478" +></A +><P +><B +>Example 4-28. parsing a MIME message</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailmime * mime; + size_t current_index; + + current_index = 0; + r = mailmime_parse(mem, stat_info.st_size, + ¤t_index, &mime); + if (r == MAILIMF_NO_ERROR) { + display_mime(mime); + /* do the things */ + status = EXIT_SUCCESS; + mailmime_free(mime); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-BASE64-BODY-PARSE" +>mailmime_base64_body_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_base64_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + </PRE +><P +> This function will parse a body part encoded using base64. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string encoded using + base64. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + The result must be freed with + <B +CLASS="COMMAND" +>mmap_string_unref()</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2501" +></A +><P +><B +>Example 4-29. Parsing a base64 encoded part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_base64_body_parse(mem, stat_info.st_size, + ¤t_index, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-QUOTED-PRINTABLE-BODY-PARSE" +>mailmime_quoted_printable_body_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_quoted_printable_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len, int in_header); + </PRE +><P +> This function will parse a body part encoded using quoted + printable. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string encoded using + quoted printable. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + The result must be freed with + <B +CLASS="COMMAND" +>mmap_string_unref()</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2524" +></A +><P +><B +>Example 4-30. Parsing a quoted printable encoded part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_quoted_printable_body_parse(mem, stat_info.st_size, + ¤t_index, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-BINARY-BODY-PARSE" +>mailmime_binary_body_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_binary_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + </PRE +><P +> This function will parse a body part encoded using binary + (no encoding). + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string encoded using + binary. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + The result must be freed with + <B +CLASS="COMMAND" +>mmap_string_unref()</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2547" +></A +><P +><B +>Example 4-31. Parsing a binary encoded part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_binary_body_parse(mem, stat_info.st_size, + ¤t_index, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-PART-PARSE" +>mailmime_part_parse</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +int mailmime_part_parse(const char * message, size_t length, + size_t * index, + int encoding, char ** result, size_t * result_len); + </PRE +><P +> This function will parse a body part encoded using a + given MIME encoding mechanism. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string encoded using + binary. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>encoding</B +> is a MIME encoding + mechanism. The value can be + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_7BIT</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_8BIT</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BINARY</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_QUOTED_PRINTABLE</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BASE64</B +> or + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_TOKEN</B +> + (see <A +HREF="#MAILMIME-MECHANISM" +>the Section called <I +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + The result must be freed with + <B +CLASS="COMMAND" +>mmap_string_unref()</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2580" +></A +><P +><B +>Example 4-32. Parsing a MIME encoded part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_part_parse(mem, stat_info.st_size, ¤t_index, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN2583" +>Rendering of MIME parts</A +></H2 +><DIV +CLASS="SECT2" +><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELDS-WRITE" +>mailmime_fields_write, mailmime_content_write and + mailmime_content_type_write</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields); + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_fields_write</B +> render the MIME + header fields. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_content_write</B +> render the MIME + content type header field. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_content_write</B +> render the + content of the MIME content type header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>col</B +> current column is given for wrapping + purpose in <B +CLASS="COMMAND" +>(* col)</B +>, + the resulting columns will be returned.. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>f</B +> is the file descriptor. It can be + stdout for example. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fields</B +> is the header fields + (see <A +HREF="#MAILMIME-FIELDS" +>the Section called <I +>mailmime_fields - header fields</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>content</B +> is the header fields + (see <A +HREF="#MAILMIME-CONTENT" +>the Section called <I +>mailmime_content - MIME content type (Content-Type)</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2610" +></A +><P +><B +>Example 4-33. rendering MIME header fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_mime * mime_fields; + int col; + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + col = 0; + mailmime_fields_write(stdout, &col, mime_fields); + + mailmime_fields_free(mime_fields); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + int col; + + /* look at the example in mailmime_content to see how to + build a mailmime_fields */ + content = build_mime_content(); + + col = 0; + mailmime_content_write(stdout, &col, mime_fields); + + mailmime_content_free(content); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + int col; + + /* look at the example in mailmime_content to see how to + build a mailmime_fields */ + content = build_mime_content(); + + col = 0; + mailmime_content_type_write(stdout, &col, mime_fields); + + mailmime_content_free(content); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-WRITE" +>mailmime_write</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info); + </PRE +><P +> This function will render a MIME message. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>col</B +> current column is given for wrapping + purpose in <B +CLASS="COMMAND" +>(* col)</B +>, + the resulting columns will be returned.. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>f</B +> is the file descriptor. It can be + stdout for example. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>build_info</B +> is the MIME message to + render. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-QUOTED-PRINTABLE-WRITE" +>mailmime_quoted_printable_write + and mailmime_base64_write</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size); + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_quoted_printable_write()</B +> will + render a string to quoted printable. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_base64_write()</B +> will + render a string to base64. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>col</B +> current column is given for wrapping + purpose in <B +CLASS="COMMAND" +>(* col)</B +>, + the resulting columns will be returned.. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>f</B +> is the file descriptor. It can be + stdout for example. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>text</B +> is the string to render. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>size</B +> is the size of the string to + render. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2649" +></A +><P +><B +>Example 4-34. render base64 or quoted printable</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + int col; + + col = 0; + mailmime_quoted_printable_write(stdout, &col, + "this is a test", 14); +} + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + int col; + + col = 0; + mailmime_base64_write(stdout, &col, "this is a test", 14); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-DATA-WRITE" +>mailmime_data_write</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_data_write</B +> will + render MIME data. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>col</B +> current column is given for wrapping + purpose in <B +CLASS="COMMAND" +>(* col)</B +>, + the resulting columns will be returned.. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>f</B +> is the file descriptor. It can be + stdout for example. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>data</B +> is the data to render + (see <A +HREF="#MAILMIME-DATA" +>the Section called <I +>mailmime_data - Content of MIME part</I +></A +>). + </P +></LI +></UL +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN2669" +>Creation functions</A +></H2 +><DIV +CLASS="SECT2" +><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-DISPOSITION-NEW-FILENAME" +>mailmime_disposition_new_filename and + mailmime_disposition_new_with_data</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition * +mailmime_disposition_new_filename(int type, char * filename); + +struct mailmime_disposition * +mailmime_disposition_new_with_data(int type, + char * filename, char * creation_date, char * modification_date, + char * read_date, size_t size); + </PRE +><P +> These functions will create a MIME content disposition + information. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>type</B +> a standard MIME disposition : + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_INLINE</B +> or + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_ATTACHMENT</B +>. + </P +><P +> <B +CLASS="COMMAND" +>filename</B +> is the filename. + </P +><P +> <B +CLASS="COMMAND" +>creation_date</B +> is the creation date. + </P +><P +> <B +CLASS="COMMAND" +>modification_date</B +> is the modification + date. + </P +><P +> <B +CLASS="COMMAND" +>read_date</B +> is the last read date. + </P +><P +> <B +CLASS="COMMAND" +>size</B +> is the size of the file. + </P +></LI +><LI +><P +> This will return a MIME content disposition + (see <A +HREF="#MAILMIME-DISPOSITION" +>the Section called <I +>mailmime_disposition - MIME disposition information (Content-Disposition)</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2694" +></A +><P +><B +>Example 4-35. creating a MIME content disposition</B +></P +><PRE +CLASS="PROGRAMLISTING" +> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_disposition * disposition; + + disposition = + mailmime_disposition_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + strdup("foo-bar.txt")); + + /* do the things */ + + mailmime_disposition_free(disposition); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELDS-NEW-EMPTY" +>mailmime_fields_new_empty and mailmime_fields_add</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_fields * mailmime_fields_new_empty(void); + +int mailmime_fields_add(struct mailmime_fields * fields, + struct mailmime_field * field); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_fields_new_empty()</B +> will + create a new empty MIME header fields list. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_fields_add()</B +> will add + MIME header fields to the MIME header fields list. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fields</B +>. The MIME header field will + be added to this MIME header fields list + (see <A +HREF="#MAILMIME-FIELDS" +>the Section called <I +>mailmime_fields - header fields</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>field</B +> is the MIME header field to add + (see <A +HREF="#MAILMIME-FIELD" +>the Section called <I +>mailmime_field - MIME header field</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2713" +></A +><P +><B +>Example 4-36. creating a MIME header fields list</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_fields * fields; + struct mailmime_field * field; + + fields = mailmime_fields_new_empty(); + field = build_mime_field(); + + /* do the things */ + + mailmime_fields_add(fields, field); + + mailmime_fields_free(fields); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELDS-NEW-WITH-DATA" +>mailmime_fields_new_with_data and + mailmime_fields_new_with_version</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_fields * +mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +struct mailmime_fields * +mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_fields_new_with_data()</B +> will + create a MIME header fields list with all the given fields + (<B +CLASS="COMMAND" +>NULL</B +> can be used for the value if the + field must not be present). + <B +CLASS="COMMAND" +>MIME-Version</B +> header field will + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>not</I +></SPAN +> be added. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_fields_new_with_version()</B +> will + create a MIME header fields list with all the given fields + (<B +CLASS="COMMAND" +>NULL</B +> can be used for the value if the + field must not be present). + <B +CLASS="COMMAND" +>MIME-Version</B +> header field will be added. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2728" +></A +><P +><B +>Example 4-37. creating new fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_disposition * disposition; + struct mailmime_fields * mime_fields; + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL); + + disposition = + mailmime_disposition_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + strdup("foo-bar.txt")); + + mime_fields = mailmime_fields_new_with_version(encoding, NULL, + NULL, disposition, NULL); + + /* do the things */ + + mailmime_fields_free(mime_fields); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-GET-CONTENT-MESSAGE" +>mailmime_get_content_message</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_content * mailmime_get_content_message(void); + +struct mailmime_content * mailmime_get_content_text(void); + +struct mailmime_content * mailmime_content_new_with_str(const char * str); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_get_content_message()</B +> will + create a MIME content type + <B +CLASS="COMMAND" +>message/rfc822</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_get_content_text()</B +> will + create a MIME content type + <B +CLASS="COMMAND" +>plain/text</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_get_content_new_with_str()</B +> will + create a MIME content type given by the string + <B +CLASS="COMMAND" +>plain/text</B +>. + </P +><P +> <B +CLASS="COMMAND" +>str</B +>. This string will + <B +CLASS="COMMAND" +>NOT</B +> be referenced by any structure. + This string will only be parsed to create the structure. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2746" +></A +><P +><B +>Example 4-38. Creating a MIME content type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + + content = mailmime_get_content_message(); + + /* do the things */ + + mailmime_content_free(content); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + /* do the things */ + + mailmime_content_free(content); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + + content = mailmime_get_content_new_with_str("multipart/mixed"); + + /* do the things */ + + mailmime_content_free(content); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-DATA-NEW-DATA" +>mailmime_data_new_data and mailmime_data_new_file</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_data * +mailmime_data_new_data(int encoding, int encoded, + const char * data, size_t length); + +struct mailmime_data * +mailmime_data_new_file(int encoding, int encoded, + char * filename); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_data_new_data()</B +> will create a + new MIME content, using a string in memory. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_data_new_file()</B +> will create a + new MIME content, using a file. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>encoding</B +> is the MIME encoding + mechanism used to encode this part. The value can be + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_7BIT</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_8BIT</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BINARY</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_QUOTED_PRINTABLE</B +> or + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BASE64</B +> + (see <A +HREF="#MAILMIME-MECHANISM" +>the Section called <I +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>encoded</B +> is set to 1 if the part is + already encoded with the mechanism given in + <B +CLASS="COMMAND" +>encoding</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>data</B +> is a pointer to the + content of the part. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the length of the data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>filename</B +> is the name of the file. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2779" +></A +><P +><B +>Example 4-39. creating MIME content</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define DATA_STR "my data" + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new_data(MAILMIME_MECHANISM_BASE64, 0, + DATA_STR, sizeof(DATA_STR) - 1); + + /* do the things */ + + mailmime_data_free(data); +} + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new_file(MAILMIME_MECHANISM_BASE64, 0, + strdup("foo-bar.txt")); + + /* do the things */ + + mailmime_data_free(data); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-NEW-MESSAGE-DATA" +>mailmime_new_message_data, mailmime_new_empty and + mailmime_new_with_content</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime * +mailmime_new_message_data(struct mailmime * msg_mime); + +struct mailmime * +mailmime_new_empty(struct mailmime_content * content, + struct mailmime_fields * mime_fields); + +int +mailmime_new_with_content(const char * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result); + +struct mailmime * mailmime_multiple_new(const char * type); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_new_message_data()</B +> will create a + new MIME message with the given subpart. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_new_empty()</B +> will create a + new MIME part with the given content type and MIME fields + but with no content. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_new_with_content()</B +> will create a + new MIME part with a content type given by a string and a + given MIME fields list. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_multiple_new()</B +> will create a + new MIME multipart with a content type given by a string. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>msg_mime</B +> is the sub part to add to the + MIME message when creating it + (see <A +HREF="#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>content</B +> is the content type of the part + to create + (see <A +HREF="#MAILMIME-CONTENT" +>the Section called <I +>mailmime_content - MIME content type (Content-Type)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>content_type</B +> is the content type of + the part to create given by a string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mime_fields</B +> is the list of MIME + header fields + (see <A +HREF="#MAILMIME-FIELDS" +>the Section called <I +>mailmime_fields - header fields</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2809" +></A +><P +><B +>Example 4-40. creating a MIME part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define DATA_STR "my data" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailmime * single_part; + + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + mailmime_new_with_content("plain/text", mime_fields, &single_part); + + mailmime_set_body_text(single_part, DATA_STR, sizeof(DATA_STR) - 1); + + mime = mailmime_new_message_data(single_part); + + /* do the things */ + + mailmime_free(mime); +} + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailmime * single_part; + struct mailmime_content * content; + + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + content = mailmime_get_content_text(); + single_part = mailmime_new_empty(content, mime_fields); + + mailmime_set_body_text(single_part, DATA_STR, sizeof(DATA_STR) - 1); + + mime = mailmime_new_message_data(single_part); + + /* do the things */ + + mailmime_free(mime); +} + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + + mime = mailmime_multiple_new("multipart/mixed"); + + /* do the things */ + + mailmime_free(mime); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-SET-PREAMBLE-FILE" +>mailmime_set_preamble_file, mailmime_set_epilogue_file, + mailmime_set_preamble_text and mailmime_set_epilogue_text</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_set_preamble_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_epilogue_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_preamble_text(struct mailmime * build_info, + char * data_str, size_t length); + +int mailmime_set_epilogue_text(struct mailmime * build_info, + char * data_str, size_t length); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_set_preamble_file()</B +> will define + the preamble of a multipart. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_set_preamble_text()</B +> will define + the preamble of a multipart. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_set_epilogue_file()</B +> will define + the epilogue of a multipart. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_set_preamble_text()</B +> will define + the preamble of a multipart. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>build_info</B +> is the MIME part to modify + (see <A +HREF="#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>data_str</B +> is the string to define + as epilogue or prologue. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the length of the string to + define as epilogue or prologue. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>filename</B +> is the name of the file + which content will be defined as epilogue or prologue. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2837" +></A +><P +><B +>Example 4-41. setting preamble and epilogue</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define DATA_STR "test foo bar" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + + mime = mailmime_multiple_new("multipart/mixed"); + + mailmime_set_preamble_file(mime, strdup("foo-bar.txt")); + + mailmime_set_epilogue_data(mime, DATA_STR, sizeof(DATA_STR) - 1); + + /* do the things */ + + mailmime_free(mime); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-SET-BODY-FILE" +>mailmime_set_body_file and mailmime_set_body_text</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_set_body_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_body_text(struct mailmime * build_info, + char * data_str, size_t length); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_set_body_file()</B +> will define + the body of a single part. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_set_body_text()</B +> will define + the body of a single part. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>build_info</B +> is the MIME part to modify + (see <A +HREF="#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>data_str</B +> is the string to define + as the body of the part. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the length of the string to + define as the body of the part. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>filename</B +> is the name of the file + which content will be defined as the body of the part. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2861" +></A +><P +><B +>Example 4-42. creating a MIME part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define DATA_STR "my data" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + mailmime_new_with_content("plain/text", mime_fields, &mime); + + mailmime_set_body_text(mime, DATA_STR, sizeof(DATA_STR) - 1); + + + + /* do the things */ + + mailmime_free(mime); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-ADD-PART" +>mailmime_add_part, mailmime_remove_part, + mailmime_smart_add_part and mailmime_smart_remove_part</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_add_part(struct mailmime * build_info, + struct mailmime * part); + +void mailmime_remove_part(struct mailmime * mime); + +int mailmime_smart_add_part(struct mailmime * mime, + struct mailmime * mime_sub); + +int mailmime_smart_remove_part(struct mailmime * mime); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_add_part()</B +> will add a sub MIME + part. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_remove_part()</B +> will detach the + given sub part from its parent. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_smart_add_part()</B +> will add a sub + MIME part. If the parent part is a message and no child + exist, the part is set as the child. If the parent part is a + message and a child already exists, if the child is + multipart, the part to add is added as child of this + multipart, else a multipart is added and the part is added + as child of the multipart. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_smart_remove_part()</B +> will detach + the given sub part from its parent. The sub part will be + freed. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>build_info</B +> is the parent MIME part + (see <A +HREF="#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>part</B +> is the part to add + (see <A +HREF="#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mime</B +> is the parent MIME part + (see <A +HREF="#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mime_sub</B +> is the part to add or to + detach + (see <A +HREF="#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2892" +></A +><P +><B +>Example 4-43. modifying MIME structure</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_add_part(mime, sub_mime); + + /* do the things */ + + mailmime_free(mime); + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime * other_sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + sub_mime = mailmime_new_empty(content, mime_fields); + + content = mailmime_get_content_text(); + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + other_sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_smart_add_part(mime, sub_mime); + mailmime_smart_add_part(mime, other_sub_mime); + + /* do the things */ + + mailmime_free(mime); + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_add_part(mime, sub_mime); + + mailmime_remove_part(sub_mime); + + /* do the things */ + + mailmime_free(sub_mime); + mailmime_free(mime); + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_add_part(mime, sub_mime); + + mailmime_smart_remove_part(sub_mime); + + /* do the things */ + + mailmime_free(mime); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-SET-IMF-FIELDS" +>mailmime_set_imf_fields</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +void mailmime_set_imf_fields(struct mailmime * build_info, + struct mailimf_fields * fields); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_set_imf_fields()</B +> will set the + fields of the given MIME message. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>build_info</B +> is the MIME message to + modify + (see <A +HREF="#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fields</B +> is the header fields to set + for the message + (see <A +HREF="#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +> in Chapter 3</A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2909" +></A +><P +><B +>Example 4-44. modifying MIME structure</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define DATA_STR "test foo bar" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailmime_fields * mime_fields; + struct mailimf_fields * imf_fields; + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT); + + mailmime_new_with_content("text/plain", mime_fields, &mime); + + mailmime_set_body_text(mime, DATA_STR, sizeof(DATA_STR) - 1); + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + imf_fields = build_fields(); + + mailmime_set_imf_fields(mime, imf_fields); + + /* do the things */ + + mailmime_free(mime); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELDS-NEW-ENCODING" +>mailmime_fields_new_encoding and + mailmime_fields_new_filename</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_fields * mailmime_fields_new_encoding(int encoding_type); + +struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, + char * filename, int encoding_type); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_fields_new_encoding()</B +> will + create a list of MIME header fields with only + <B +CLASS="COMMAND" +>Content-Transfer-Encoding</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_fields_new_filename()</B +> will + create a list of MIME header fields with + <B +CLASS="COMMAND" +>Content-Transfer-Encoding</B +> and + <B +CLASS="COMMAND" +>Content-Disposition</B +>. + </P +><P +> The result will be a list of MIME header fields + (see <A +HREF="#MAILMIME-FIELDS" +>the Section called <I +>mailmime_fields - header fields</I +></A +>). + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>encoding_type</B +> is the MIME encoding + mechanism. The value can be + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_7BIT</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_8BIT</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BINARY</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_QUOTED_PRINTABLE</B +> or + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BASE64</B +> + (see <A +HREF="#MAILMIME-MECHANISM" +>the Section called <I +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dsp_type</B +> is the disposition type. + The value can be + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_INLINE</B +> or + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_ATTACHMENT</B +> + (see <A +HREF="#MAILMIME-DISPOSITION-TYPE" +>the Section called <I +>mailmime_disposition_type - Type of MIME disposition</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>filename</B +> is the filename for MIME + content disposition. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2943" +></A +><P +><B +>Example 4-45. creating MIME fields with only Content-Transfer-Encoding</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(void) +{ + struct mailmime_fields * fields; + + fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + /* do the things */ + + mailmime_fields_free(fields); +} + +int main(void) +{ + struct mailmime_fields * fields; + + fields = + mailmime_fields_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + strdup("foo-bar.txt"), MAILMIME_MECHANISM_BASE64); + + /* do the things */ + + mailmime_fields_free(fields); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN2946" +>Helper functions</A +></H2 +><DIV +CLASS="SECT2" +><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-TRANSFER-ENCODING-GET" +>mailmime_transfer_encoding_get</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_transfer_encoding_get(struct mailmime_fields * fields); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_transfer_encoding_get()</B +> will + return the standard MIME encoding mechanism. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fields</B +> is the list of MIME header + fields. + </P +></LI +><LI +><P +> An integer representing the MIME encoding mechanism will + be returned + (see <A +HREF="#MAILMIME-MECHANISM" +>the Section called <I +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2960" +></A +><P +><B +>Example 4-46. extracting MIME encoding mechanism</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + struct mailmime_fields * mime_fields; + + r = mailmime_fields_parse(f, &mime_fields); + if (r == MAILIMF_NO_ERROR) { + int encoding; + + encoding = mailmime_transfer_encoding_get(mime_fields); + + /* do the things */ + + mailmime_fields_free(mime_fields); + status = EXIT_SUCCESS; + } + + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMIME-CONTENT-CHARSET-GET" +>mailmime_content_charset_get and + mailmime_content_param_get</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +char * mailmime_content_charset_get(struct mailmime_content * content); + +char * mailmime_content_param_get(struct mailmime_content * content, + char * name); + +char * mailmime_extract_boundary(struct mailmime_content * content_type); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_content_charset_get()</B +> will + return the <B +CLASS="COMMAND" +>charset</B +> parameter of + MIME content type. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_content_param_get()</B +> will + return the value of a given parameter of + MIME content type. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_extract_boundary()</B +> will + return the <B +CLASS="COMMAND" +>charset</B +> parameter of + MIME content type. + </P +><P +></P +><UL +><LI +><P +> + <B +CLASS="COMMAND" +>content</B +> is the MIME content type. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>name</B +> is the name of the parameter to + extract. + </P +></LI +><LI +><P +> With <B +CLASS="COMMAND" +>mailmime_extract_boundary()</B +>, the + returned value must be freed with + <B +CLASS="COMMAND" +>free()</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2985" +></A +><P +><B +>Example 4-47. extracting information from MIME content type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Type") == 0) { + struct mailmime_content * content_type; + size_t current_index; + + current_index = 0; + r = mailmime_content_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &content_type); + if (r == MAILIMF_NO_ERROR) { + char * charset; + char * name; + char * boundary; + + charset = mailmime_content_charset_get(content_type); + name = mailmime_content_param_get(content_type, "name"); + boundary = mailmime_extract_boundary(content_type); + + /* do the things */ + + free(boundary); + + status = EXIT_SUCCESS; + mailmime_content_free(content_type); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +></DIV +></DIV +><DIV +CLASS="CHAPTER" +><HR><H1 +><A +NAME="AEN2988" +></A +>Chapter 5. Storages, folders, messages</H1 +><DIV +CLASS="SECT1" +><H2 +CLASS="SECT1" +><A +NAME="AEN2990" +>Introduction</A +></H2 +><P +> This part will give the definition of some objects. + </P +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN2993" +>Message</A +></H3 +><P +> A message is the common e-mail message or news message you + read or send. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN2996" +>MIME part</A +></H3 +><P +> A message can have attachment such as images or other documents. + The attachment are organized into a tree structure. Each + node of this structure is a MIME part. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN2999" +>Mailbox</A +></H3 +><P +> A mailbox will contain a given number of messages. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3002" +>Storage</A +></H3 +><P +> A storage is a "physical" localisation of your mailbox. This + can be on a filesystem (local or remote disk, this is the + case of MH, mbox and maildir), or this can be on a remote + host (this is the case for POP3, IMAP or NNTP). + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3005" +>Folder</A +></H3 +><P +> A storage, for the same user, can contain a given number of + mailboxes, depending the storage capabilities, then, the + storage driver capabilities. With etPan!, MH, IMAP and NNTP + storages can have more than one mailbox. The mailboxes will + be called folders. On storage where we only have one + mailbox, the unique mailbox is the unique folder. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3008" +>Session</A +></H3 +><P +> The session is the network connection or the entity to which + the commands of the drivers are given. + </P +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN3011" +>Error codes</A +></H2 +><P +> Error codes returned as integers can be one of the following : + </P +><PRE +CLASS="PROGRAMLISTING" +>enum { + MAIL_NO_ERROR = 0, + MAIL_NO_ERROR_AUTHENTICATED, + MAIL_NO_ERROR_NON_AUTHENTICATED, + MAIL_ERROR_NOT_IMPLEMENTED, + MAIL_ERROR_UNKNOWN, + MAIL_ERROR_CONNECT, + MAIL_ERROR_BAD_STATE, + MAIL_ERROR_FILE, + MAIL_ERROR_STREAM, + MAIL_ERROR_LOGIN, + MAIL_ERROR_CREATE, /* 10 */ + MAIL_ERROR_DELETE, + MAIL_ERROR_LOGOUT, + MAIL_ERROR_NOOP, + MAIL_ERROR_RENAME, + MAIL_ERROR_CHECK, + MAIL_ERROR_EXAMINE, + MAIL_ERROR_SELECT, + MAIL_ERROR_MEMORY, + MAIL_ERROR_STATUS, + MAIL_ERROR_SUBSCRIBE, /* 20 */ + MAIL_ERROR_UNSUBSCRIBE, + MAIL_ERROR_LIST, + MAIL_ERROR_LSUB, + MAIL_ERROR_APPEND, + MAIL_ERROR_COPY, + MAIL_ERROR_FETCH, + MAIL_ERROR_STORE, + MAIL_ERROR_SEARCH, + MAIL_ERROR_DISKSPACE, + MAIL_ERROR_MSG_NOT_FOUND, /* 30 */ + MAIL_ERROR_PARSE, + MAIL_ERROR_INVAL, + MAIL_ERROR_PART_NOT_FOUND, + MAIL_ERROR_REMOVE, + MAIL_ERROR_FOLDER_NOT_FOUND, + MAIL_ERROR_MOVE, + MAIL_ERROR_STARTTLS, + MAIL_ERROR_CACHE_MISS, + MAIL_ERROR_NO_TLS, + MAIL_ERROR_EXPUNGE, + /* misc errors */ + MAIL_ERROR_MISC, + MAIL_ERROR_PROTOCOL, + MAIL_ERROR_CAPABILITY, + MAIL_ERROR_CLOSE, + MAIL_ERROR_FATAL, + MAIL_ERROR_READONLY, + MAIL_ERROR_NO_APOP, + MAIL_ERROR_COMMAND_NOT_SUPPORTED, + MAIL_ERROR_NO_PERMISSION, + MAIL_ERROR_PROGRAM_ERROR, + MAIL_ERROR_SUBJECT_NOT_FOUND, + MAIL_ERROR_CHAR_ENCODING_FAILED, + MAIL_ERROR_SEND, + MAIL_ERROR_COMMAND, +}; + </PRE +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN3015" +>Storage</A +></H2 +><DIV +CLASS="SECT2" +><H3 +CLASS="SECT2" +><A +NAME="MAILSTORAGE-DRIVER" +>Storage driver</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +typedef struct mailstorage_driver mailstorage_driver; + +struct mailstorage_driver { + char * sto_name; + int (* sto_connect)(struct mailstorage * storage); + int (* sto_get_folder_session)(struct mailstorage * storage, + char * pathname, mailsession ** result); + void (* sto_uninitialize)(struct mailstorage * storage); +}; + </PRE +><P +> This is the driver for a storage. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>sto_name</B +> is the name of the driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_connect()</B +> connects the storage to + the remote access or to the path in the local filesystem. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_get_folder_session()</B +> can have two + kinds of behaviour. Either it creates a new session and + independant from the session used by the storage and + select the given mailbox or it selects the given mailbox + in the current session. It depends on the efficiency of + the mail access. + </P +><P +> <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>XXX - in the future, this will be moved to the + folder driver</I +></SPAN +> + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_uninitialize()</B +> frees the data + created with mailstorage constructor. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILSTORAGE" +>Storage</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailstorage { + char * sto_id; + void * sto_data; + mailsession * sto_session; + mailstorage_driver * sto_driver; + clist * sto_shared_folders; /* list of (struct mailfolder *) */ + + void * sto_user_data; +}; + </PRE +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>sto_id</B +> is an identifier for the + storage. This can be <B +CLASS="COMMAND" +>NULL</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_data</B +> is the internal data + of the storage. This can only be changed by the driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_session</B +> is the session used by + the storage. The session can be used to send commands. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_driver</B +> is the driver of the + storage. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_shared_folders</B +> is the list of + folders that share the session with the storage. + This is used internally. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_user_data</B +> is a field for free + use. The user can store any data in that field. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILSTORAGE-NEW" +>mailstorage_new and mailstorage_free</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailstorage * mailstorage_new(char * sto_id); + +void mailstorage_free(struct mailstorage * storage); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstorage_new()</B +> initializes a storage + structure with an identifier (<B +CLASS="COMMAND" +>sto_id</B +>) and + with no driver. + </P +><P +> <B +CLASS="COMMAND" +>mailstorage_free()</B +> free the memory used + by a storage. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILSTORAGE-CONNECT" +>mailstorage_connect and mailstorage_disconnect</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailstorage_connect(struct mailstorage * storage); + +void mailstorage_disconnect(struct mailstorage * storage); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstorage_connect()</B +> connects the storage. + This function can also be used to confirm that a storage + connection is valid when the storage is already connected. + </P +><P +> <B +CLASS="COMMAND" +>mailstorage_disconnect()</B +> disconnects the + storage. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3074" +>IMAP storage</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int imap_mailstorage_init(struct mailstorage * storage, + char * imap_servername, uint16_t imap_port, + char * imap_command, + int imap_connection_type, int imap_auth_type, + char * imap_login, char * imap_password, + int imap_cached, char * imap_cache_directory); + </PRE +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3077" +>Example</A +></H3 +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN3079" +></A +><P +><B +>Example 5-1. use of storage</B +></P +><PRE +CLASS="PROGRAMLISTING" +>int main(void) +{ + struct mailstorage * storage; + int r; + + storage = mailstorage_new(NULL); + + imap_mailstorage_init(storage, "imap.my-servers.org", 0, + NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN, + "my-login", "my-password", 1, "/home/login/.libetpan/cache"); + + r = mailstorage_connect(storage); + if (r == MAIL_NO_ERROR) { + mailstorage_disconnect(storage); + } + + mailstorage_free(storage); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN3082" +>Folder</A +></H2 +><DIV +CLASS="SECT2" +><H3 +CLASS="SECT2" +><A +NAME="MAILFOLDER-DRIVER" +>Folder driver</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +typedef struct mailfolder_driver mailfolder_driver; + +struct mailfolder_driver { + int (* fld_get_session)(struct mailfolder * folder, + mailsession ** result); + + int (* fld_noop)(struct mailfolder * folder); + + int (* fld_check)(struct mailfolder * folder); + + int (* fld_expunge)(struct mailfolder * folder); + + int (* fld_status)(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + + int (* fld_append_message)(struct mailfolder * folder, + char * message, size_t size); + + int (* fld_get_messages_list)(struct mailfolder * folder, + struct mailmessage_list ** result); + + int (* fld_get_envelopes_list)(struct mailfolder * folder, + struct mailmessage_list * result); + + int (* fld_get_message)(struct mailfolder * folder, + uint32_t num, mailmessage ** result); + + int (* fld_get_message_by_uid)(struct mailfolder * folder, + const char * uid, mailmessage ** result); +} + </PRE +><P +> XXX - this will be implemented in the future. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fld_get_session()</B +> will return the session + this folder should use. + </P +></LI +><LI +><P +> For other method, you should see <A +HREF="#MAILSESSION-DRIVER" +>the Section called <I +>Session driver</I +></A +>. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3095" +>Folder</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailfolder { + char * fld_pathname; + char * fld_virtual_name; + + struct mailstorage * fld_storage; + + mailsession * fld_session; + int fld_shared_session; + clistiter * fld_pos; + + struct mailfolder * fld_parent; + unsigned int fld_sibling_index; + carray * fld_children; /* array of (struct mailfolder *) */ + + void * fld_user_data; +}; + </PRE +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fld_pathname</B +> is the pathname specific to + the driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_virtual_name</B +> is the identifier of + this folder. This can be <B +CLASS="COMMAND" +>NULL</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_storage</B +> is the storage used for this + folder (see <A +HREF="#MAILSTORAGE" +>the Section called <I +>Storage</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_session</B +> is the session used for this + folder. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_shared_session</B +> is set to 1 if the + folder use the same session as the storage. This is used + internally. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_pos</B +> is the + position in the list of folders of the storage. + This is used internally. + </P +></LI +><LI +><P +> use of <B +CLASS="COMMAND" +>fld_parent</B +>, + <B +CLASS="COMMAND" +>fld_sibling_index</B +> and + <B +CLASS="COMMAND" +>fld_children</B +> is deprecated. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_user_data</B +> is a field for free + use. The user can store any data in that field. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILFOLDER-NEW" +>mailfolder_new and mail_folder_free</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailfolder * mailfolder_new(struct mailstorage * fld_storage, + char * fld_pathname, char * fld_virtual_name); + +void mailfolder_free(struct mailfolder * folder); + </PRE +><P +> <B +CLASS="COMMAND" +>mailfolder_new()</B +> initializes a folder + structure with an identifier + (<B +CLASS="COMMAND" +>fld_virtual_name</B +>) with path name + (<B +CLASS="COMMAND" +>fld_pathname</B +>). The folder will be owned + by the given storage (<B +CLASS="COMMAND" +>fld_storage</B +>). + </P +><P +> <B +CLASS="COMMAND" +>mailfolder_free()</B +> free the memory used + by the folder. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILFOLDER-CONNECT" +>mailfolder_connect and mailfolder_disconnect</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailfolder_connect(struct mailfolder * folder); + +void mailfolder_disconnect(struct mailfolder * folder); + </PRE +><P +> <B +CLASS="COMMAND" +>mailfolder_connect()</B +> connects the folder. + This function can also be used to confirm that a folder + connection is valid when the folder is already connected. + When doing operations with several folders, you have to be + sure that this function has been called before making calls + on folder. + </P +><P +> <B +CLASS="COMMAND" +>mailfolder_disconnect()</B +> disconnects the + folder. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILFOLDER-NOOP" +>mailfolder_noop</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailfolder_noop(struct mailfolder * folder); + </PRE +><P +> This function will only send noop to the mail access. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILFOLDER-CHECK" +>mailfolder_check</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailfolder_check(struct mailfolder * folder); + </PRE +><P +> A call to this function will save to disk the internal state + of the selected mailbox (such as flags). + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILFOLDER-EXPUNGE" +>mailfolder_expunge</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailfolder_expunge(struct mailfolder * folder); + </PRE +><P +> A call to this function will delete all messages marked for + deletion. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILFOLDER-STATUS" +>mailfolder_status</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int mailfolder_status(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + </PRE +><P +> A call to this function will return some counts of messages + in the mailbox. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILFOLDER-APPEND-MESSAGE" +>mailfolder_append_message</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int mailfolder_append_message(struct mailfolder * folder, + char * message, size_t size); + </PRE +><P +> This function will store a new message in the given folder. + The message is given by a string in memory + (<B +CLASS="COMMAND" +>message</B +>) and a size + (<B +CLASS="COMMAND" +>size</B +>). + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILFOLDER-GET-MESSAGES-LIST" +>mailfolder_get_messages_list</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int mailfolder_get_messages_list(struct mailfolder * folder, + struct mailmessage_list ** result); + </PRE +><P +> This function will return the list of messages in the given + folder (see <A +HREF="#MAILMESSAGE-LIST" +>the Section called <I +>Message list</I +></A +>). + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILFOLDER-GET-ENVELOPES-LIST" +>mailfolder_get_envelopes_list</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int mailfolder_get_envelopes_list(struct mailfolder * folder, + struct mailmessage_list * result); + </PRE +><P +> This function will fill the list of parsed header fields + structure in the <B +CLASS="COMMAND" +>mailmessage</B +> structures + of the given list of messages (<B +CLASS="COMMAND" +>result</B +>). + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILFOLDER-GET-MESSAGE" +>mailfolder_get_message</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int mailfolder_get_message(struct mailfolder * folder, + uint32_t num, mailmessage ** result); + </PRE +><P +> This function will return the message identified by a + message index (<B +CLASS="COMMAND" +>num</B +>) + This will return a <B +CLASS="COMMAND" +>mailmessage</B +> structure + in <B +CLASS="COMMAND" +>(* result)</B +> (see <A +HREF="#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>). + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILFOLDER-GET-MESSAGE-BY-UID" +>mailfolder_get_message_by_uid</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>int mailfolder_get_message_by_uid(struct mailfolder * folder, + const char * uid, mailmessage ** result); + </PRE +><P +> This function will return the message identified by a + unique identifier (<B +CLASS="COMMAND" +>uid</B +>) + This will return a <B +CLASS="COMMAND" +>mailmessage</B +> structure + in <B +CLASS="COMMAND" +>(* result)</B +> (see <A +HREF="#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>). + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3193" +>Example</A +></H3 +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN3195" +></A +><P +><B +>Example 5-2. use of folder</B +></P +><PRE +CLASS="PROGRAMLISTING" +>int main(void) +{ + struct mailstorage * storage; + int r; + + storage = mailstorage_new(NULL); + + imap_mailstorage_init(storage, "imap.my-servers.org", 0, + NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN, + "my-login", "my-password", 1, "/home/login/.libetpan/cache"); + + r = mailstorage_connect(storage); + if (r == MAIL_NO_ERROR) { + struct mailfolder * folder; + + folder = mailfolder_new(storage, "INBOX", NULL); + + r = mailfolder_connect(folder); + if (r == MAIL_NO_ERROR) { + struct mailmessage_list * msg_list; + + mailfolder_get_messages_list(folder, &msg_list); + + /* do the things */ + + mailmessage_list_free(msg_list); + + mailfolder_disconnect(folder); + } + + mailstorage_disconnect(storage); + } + + mailstorage_free(storage); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN3198" +>Message</A +></H2 +><DIV +CLASS="SECT2" +><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-DRIVER" +>Message driver</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmessage_driver { + char * msg_name; + + int (* msg_initialize)(mailmessage * msg_info); + + void (* msg_uninitialize)(mailmessage * msg_info); + + void (* msg_flush)(mailmessage * msg_info); + + void (* msg_check)(mailmessage * msg_info); + + void (* msg_fetch_result_free)(mailmessage * msg_info, + char * msg); + + int (* msg_fetch)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_header)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_body)(mailmessage * msg_info, + char ** result, size_t * result_len); + + int (* msg_fetch_size)(mailmessage * msg_info, + size_t * result); + + int (* msg_get_bodystructure)(mailmessage * msg_info, + struct mailmime ** result); + + int (* msg_fetch_section)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + + int (* msg_fetch_section_header)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_mime)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_body)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_envelope)(mailmessage * msg_info, + struct mailimf_fields ** result); + + int (* msg_get_flags)(mailmessage * msg_info, + struct mail_flags ** result); +}; + </PRE +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>msg_name</B +> is the name of the driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_initialize()</B +> will initialize the + internal message state (field + <B +CLASS="COMMAND" +>msg_data</B +> of + <B +CLASS="COMMAND" +>mailmessage</B +> structure (see <A +HREF="#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_uninitialize()</B +> will free the + internal message state. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_flush()</B +> will release memory used + by the MIME structure of the message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_check()</B +> will store the flags of + the message into the session, so that the message can be + released without the flags are lost. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_result_free()</B +> will free a + string returned by any fetch_XXX() function. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch()</B +> will fetch a message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_header()</B +> will fetch the + header fields of a message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_body()</B +> will fetch a message + without its main header. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_size()</B +> will return the size + of a message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_get_bodystructure</B +> will retrieve + the MIME structure of the message. The returned + structure must <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> be freed. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_section()</B +> will fetch the + content of the section of the message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_section_header()</B +> will fetch + the header of a section of the message if the content of + the section is a message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_section_mime()</B +> will fetch + the MIME header of a section of the message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_section_body()</B +> will fetch + the body of a section (without the headers) of the + message if the content of the section is a message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_envelope()</B +> will return + a given number of parsed header fields. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_get_flags()</B +> will return the + flags of the message. + The returned structure must <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> be + freed. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE" +>Message</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmessage { + mailsession * msg_session; + mailmessage_driver * msg_driver; + uint32_t msg_index; + char * msg_uid; + + size_t msg_size; + struct mailimf_fields * msg_fields; + struct mail_flags * msg_flags; + + int msg_resolved; + struct mailimf_single_fields msg_single_fields; + struct mailmime * msg_mime; + + /* internal data */ + + int msg_cached; + void * msg_data; + + /* + msg_folder field : + used to reference the mailfolder, this is a workaround due + to the problem with initial conception, where folder notion + did not exist. + */ + void * msg_folder; + /* user data */ + void * msg_user_data; +}; + </PRE +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>msg_session</B +> is the session related to + the message + (see <A +HREF="#MAILSESSION" +>the Section called <I +>Session</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_driver</B +> is the driver used for the + message + (see <A +HREF="#MAILMESSAGE-DRIVER" +>the Section called <I +>Message driver</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_index</B +> is an index to indentify + the message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_uid</B +> is the unique identifier of + the message, valid accross disconnections. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_size</B +> is the size of the message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fields</B +> is the list of parsed + header fields of the message. This can be + <B +CLASS="COMMAND" +>NULL</B +> + (see <A +HREF="#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +> in Chapter 3</A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_flags</B +> is the flags of the + message. This can be <B +CLASS="COMMAND" +>NULL</B +> + (see <A +HREF="#MAIL-FLAGS" +>the Section called <I +>Message flags</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_resolved</B +> will tell if the field + <B +CLASS="COMMAND" +>msg_single_fields</B +> has been initialized. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_single_fields</B +> will be filled + using <B +CLASS="COMMAND" +>msg_fields</B +> + (see <A +HREF="#MAILIMF-SINGLE-FIELDS" +>the Section called <I +>mailimf_single_fields - simplified fields</I +> in Chapter 3</A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_mime</B +> is the MIME structure of the + message. It is intialized at least when + <B +CLASS="COMMAND" +>get_bodystructure()</B +> is called once. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_cached</B +> is 1 when the message was + cached. This is used internally. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_data</B +> is the internal state of the + message. The content depends on the driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_folder</B +> is used to reference the + mailfolder, this is a workaround due to the problem with + initial conception, where folder notion did not exist. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_user_data</B +> is a field for free + use. The user can store any data in that field. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-NEW" +>mailmessage_new</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +mailmessage * mailmessage_new(void); + +void mailmessage_free(mailmessage * info); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmessage_new()</B +> will create a new + message (without driver). This is used internally by + drivers. + </P +><P +> <B +CLASS="COMMAND" +>mailmessage_free()</B +> will free the memory + used by the given message. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-INIT" +>mailmessage_init</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_init(mailmessage * msg_info, + mailsession * session, + mailmessage_driver * driver, + uint32_t index, size_t size); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmessage_init()</B +> will initialize a + message with a driver. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>msg_info</B +> is the message to initialize + (see <A +HREF="#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>session</B +> is the session related to the + message + (see <A +HREF="#MAILSESSION" +>the Section called <I +>Session</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>driver</B +> is the driver to use for the + message + (see <A +HREF="#MAILMESSAGE-DRIVER" +>the Section called <I +>Message driver</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is the index of the message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>size</B +> is the size of the message. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FLUSH" +>mailmessage_flush</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_flush(mailmessage * info); + </PRE +><P +> This function will release the memory used by the MIME + structure of the message. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-CHECK" +>mailmessage_check</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_check(mailmessage * info); + </PRE +><P +> After you set some flags, if you want to notify them to the + session before destroying the message, you can use this function. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-RESULT-FREE" +>mailmessage_fetch_result_free</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_result_free(mailmessage * msg_info, + char * msg); + </PRE +><P +> This function will free a string returned by any + mailmessage_fetch_XXX() function. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH" +>mailmessage_fetch</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + </PRE +><P +> This function returns the content of the message (headers + and text). + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-HEADER" +>mailmessage_fetch_header</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + </PRE +><P +> This function returns the header of the message as a string. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-BODY" +>mailmessage_fetch_body</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + </PRE +><P +> This function returns the content of the message (without + headers). + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-SIZE" +>mailmessage_fetch_size</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_size(mailmessage * msg_info, + size_t * result); + </PRE +><P +> This function returns the size of the message content. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-GET-BODYSTRUCTURE" +>mailmessage_get_bodystructure</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + </PRE +><P +> This functions returns the MIME structure of the message. + The returned information <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>MUST</I +></SPAN +> not be + freed by hand. It is freed by + <B +CLASS="COMMAND" +>mailmessage_flush()</B +> or + <B +CLASS="COMMAND" +>mailmessage_free()</B +> + (see <A +HREF="#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +> in Chapter 4</A +>). + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-SECTION" +>mailmessage_fetch_section</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + </PRE +><P +> This function returns the content of a MIME part. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-SECTION-HEADER" +>mailmessage_fetch_section_header</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + </PRE +><P +> This function returns the header of the message contained + in the given MIME part. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-SECTION-MIME" +>mailmessage_fetch_section_mime</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + </PRE +><P +> This function returns the MIME header of the given MIME + part. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-SECTION-BODY" +>mailmessage_fetch_section_body</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + </PRE +><P +> This function returns the text part of the message contained + in the given MIME part. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-ENVELOPE" +>mailmessage_fetch_envelope</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + </PRE +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-GET-FLAGS" +>mailmessage_get_flags</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + </PRE +><P +> This function returns the flags related to the message. + The returned information MUST not be freed by hand. It is freed by + <B +CLASS="COMMAND" +>mailmessage_free()</B +>. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-RESOLVE-SINGLE-FIELDS" +>mailmessage_resolve_single_fields</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +void mailmessage_resolve_single_fields(mailmessage * msg_info); + </PRE +><P +> This function will use the fields information to fill + the single_fields structure in the mailmessage structure. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-LIST" +>Message list</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmessage_list { + carray * msg_tab; /* elements are (mailmessage *) */ +}; + +struct mailmessage_list * mailmessage_list_new(carray * msg_tab); + +void mailmessage_list_free(struct mailmessage_list * env_list); + </PRE +><P +> This is a list of messages. + </P +><P +> <B +CLASS="COMMAND" +>msg_tab</B +> is an array containing the + messages (see linkend="carray"). + </P +><P +> <B +CLASS="COMMAND" +>mailmessage_list_new()</B +> will initialize a + list of messages, using a given array of messages. + </P +><P +> <B +CLASS="COMMAND" +>mailmessage_list_free()</B +> will free the + memory used by the list of messages. This will also free the + messages. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-TREE" +>Message tree</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmessage_tree { + struct mailmessage_tree * node_parent; + char * node_msgid; + time_t node_date; + mailmessage * node_msg; + carray * node_children; /* array of (struct mailmessage_tree *) */ + + /* private, used for threading */ + int node_is_reply; + char * node_base_subject; +}; + + +struct mailmessage_tree * +mailmessage_tree_new(char * node_msgid, time_t node_date, + mailmessage * node_msg); + +void mailmessage_tree_free(struct mailmessage_tree * tree); + +void mailmessage_tree_free_recursive(struct mailmessage_tree * tree); + </PRE +><P +> This is a node of a tree of messages. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>node_parent</B +> is the parent of this + node. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>node_msgid</B +> is the content of the + field <B +CLASS="COMMAND" +>Message-ID</B +> of the message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>node_date</B +> is the date in UNIX + format. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>node_msg</B +> is the message of the node. + The message should have the <B +CLASS="COMMAND" +>msg_fields</B +> + field initialized. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>node_children</B +> is the list of + children of this node. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>node_is_reply</B +> is set to 1 if the + message is a reply. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>node_base_subject</B +> is the base subject + of the message (base subject is defined in definition of + IMAP thread draft). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailmessage_tree_new()</B +> will initialize a + message node. + </P +><P +> <B +CLASS="COMMAND" +>mailmessage_tree_free()</B +> will release + memory used by the node. This will <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> + free the message. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAIL-FLAGS" +>Message flags</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAIL_FLAG_NEW = 1 << 0, + MAIL_FLAG_SEEN = 1 << 1, + MAIL_FLAG_FLAGGED = 1 << 2, + MAIL_FLAG_DELETED = 1 << 3, + MAIL_FLAG_ANSWERED = 1 << 4, + MAIL_FLAG_FORWARDED = 1 << 5, + MAIL_FLAG_CANCELLED = 1 << 6, +}; + +struct mail_flags { + uint32_t fl_flags; + clist * fl_extension; /* elements are (char *) */ +}; + +struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_ext); + +void mail_flags_free(struct mail_flags * flags); + +int mail_flags_add_extension(struct mail_flags * flags, + char * ext_flag); + +int mail_flags_remove_extension(struct mail_flags * flags, + char * ext_flag); + +int mail_flags_has_extension(struct mail_flags * flags, + char * ext_flag); + </PRE +><P +> This is the structure containing the message flags. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fl_flags</B +> will contain the standards + flags. The value will be a combinaison (with or binary + operation) of <B +CLASS="COMMAND" +>MAIL_FLAG_XXX</B +> values. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fl_extension</B +> will be a list (see + <A +HREF="#CLIST" +>the Section called <I +>List</I +> in Chapter 2</A +>) of strings representing the + non-standard flags. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3467" +>Example</A +></H3 +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN3469" +></A +><P +><B +>Example 5-3. use of message</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define DEST_CHARSET "iso-8859-1" + +enum { + NO_ERROR, + ERROR_FILE, + ERROR_MEMORY, + ERROR_INVAL, + ERROR_FETCH, +}; + +/* returns TRUE is given MIME part is a text part */ + +int etpan_mime_is_text(struct mailmime * build_info) +{ + if (build_info->mm_type == MAILMIME_SINGLE) { + if (build_info->mm_content_type != NULL) { + if (build_info->mm_content_type->ct_type->tp_type == + MAILMIME_TYPE_DISCRETE_TYPE) { + if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type == + MAILMIME_DISCRETE_TYPE_TEXT) + return 1; + } + } + else + return 1; + } + + return 0; +} + + +/* display content type */ + +int show_part_info(FILE * f, + struct mailmime_single_fields * mime_fields, + struct mailmime_content * content) +{ + char * description; + char * filename; + int col; + int r; + + description = mime_fields->fld_description; + filename = mime_fields->fld_disposition_filename; + + col = 0; + + r = fprintf(f, " [ Part "); + if (r < 0) + goto err; + + if (content != NULL) { + r = mailmime_content_type_write(f, &col, content); + if (r != MAILIMF_NO_ERROR) + goto err; + } + + if (filename != NULL) { + r = fprintf(f, " (%s)", filename); + if (r < 0) + goto err; + } + + if (description != NULL) { + r = fprintf(f, " : %s", description); + if (r < 0) + goto err; + } + + r = fprintf(f, " ]\n\n"); + if (r < 0) + goto err; + + return NO_ERROR; + + err: + return ERROR_FILE; +} + +/* fetch message and decode if it is base64 or quoted-printable */ + +int etpan_fetch_message(mailmessage * msg_info, + struct mailmime * mime_part, + struct mailmime_single_fields * fields, + char ** result, size_t * result_len) +{ + char * data; + size_t len; + int r; + int encoding; + char * decoded; + size_t decoded_len; + size_t cur_token; + int res; + int encoded; + + encoded = 0; + + r = mailmessage_fetch_section(msg_info, + mime_part, &data, &len); + if (r != MAIL_NO_ERROR) { + res = ERROR_FETCH; + goto err; + } + + encoded = 1; + + /* decode message */ + + if (encoded) { + if (fields->fld_encoding != NULL) + encoding = fields->fld_encoding->enc_type; + else + encoding = MAILMIME_MECHANISM_8BIT; + } + else { + encoding = MAILMIME_MECHANISM_8BIT; + } + + cur_token = 0; + r = mailmime_part_parse(data, len, &cur_token, + encoding, &decoded, &decoded_len); + if (r != MAILIMF_NO_ERROR) { + res = ERROR_FETCH; + goto free; + } + + mailmessage_fetch_result_free(msg_info, data); + + * result = decoded; + * result_len = decoded_len; + + return NO_ERROR; + + free: + mailmessage_fetch_result_free(msg_info, data); + err: + return res; +} + +/* fetch fields */ + +struct mailimf_fields * fetch_fields(mailmessage * msg_info, + struct mailmime * mime) +{ + char * data; + size_t len; + int r; + size_t cur_token; + struct mailimf_fields * fields; + + r = mailmessage_fetch_section_header(msg_info, mime, + &data, &len); + if (r != MAIL_NO_ERROR) + return NULL; + + cur_token = 0; + r = mailimf_envelopes_fields_parse(data, len, + &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + mailmessage_fetch_result_free(msg_info, data); + return NULL; + } + + mailmessage_fetch_result_free(msg_info, data); + + return fields; +} + +/* render message */ + +static int etpan_render_mime(FILE * f, mailmessage * msg_info, + struct mailmime * mime) +{ + int r; + clistiter * cur; + int col; + int text; + int show; + struct mailmime_single_fields fields; + int res; + + mailmime_single_fields_init(&fields, mime->mm_mime_fields, + mime->mm_content_type); + + text = etpan_mime_is_text(mime); + + r = show_part_info(f, &fields, mime->mm_content_type); + if (r != NO_ERROR) { + res = r; + goto err; + } + + switch(mime->mm_type) { + case MAILMIME_SINGLE: + show = 0; + if (text) + show = 1; + + if (show) { + char * data; + size_t len; + char * converted; + size_t converted_len; + char * source_charset; + size_t write_len; + + /* viewable part */ + + r = etpan_fetch_message(msg_info, mime, + &fields, &data, &len); + if (r != NO_ERROR) { + res = r; + goto err; + } + + source_charset = fields.fld_content_charset; + if (source_charset == NULL) + source_charset = DEST_CHARSET; + + r = charconv_buffer(source_charset, DEST_CHARSET, + data, len, &converted, &converted_len); + if (r != MAIL_CHARCONV_NO_ERROR) { + + r = fprintf(f, "[ error converting charset from %s to %s ]\n", + source_charset, DEST_CHARSET); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + + write_len = fwrite(data, 1, len, f); + if (write_len != len) { + mailmime_decoded_part_free(data); + res = r; + goto err; + } + } + else { + write_len = fwrite(converted, 1, converted_len, f); + if (write_len != len) { + charconv_buffer_free(converted); + mailmime_decoded_part_free(data); + res = r; + goto err; + } + + charconv_buffer_free(converted); + } + + write_len = fwrite("\r\n\r\n", 1, 4, f); + if (write_len < 4) { + mailmime_decoded_part_free(data); + res = ERROR_FILE; + goto err; + } + + mailmime_decoded_part_free(data); + } + else { + /* not viewable part */ + + r = fprintf(f, " (not shown)\n\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + break; + + case MAILMIME_MULTIPLE: + + if (strcasecmp(mime->mm_content_type->ct_subtype, + "alternative") == 0) { + struct mailmime * prefered_body; + int prefered_score; + + /* case of multiple/alternative */ + + /* + we choose the better part, + alternative preference : + + text/plain => score 3 + text/xxx => score 2 + other => score 1 + */ + + prefered_body = NULL; + prefered_score = 0; + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * submime; + int score; + + score = 1; + submime = clist_content(cur); + if (etpan_mime_is_text(submime)) + score = 2; + + if (submime->mm_content_type != NULL) { + if (strcasecmp(submime->mm_content_type->ct_subtype, + "plain") == 0) + score = 3; + } + + if (score > prefered_score) { + prefered_score = score; + prefered_body = submime; + } + } + + if (prefered_body != NULL) { + r = etpan_render_mime(f, msg_info, prefered_body); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + else { + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + + r = etpan_render_mime(f, msg_info, clist_content(cur)); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + + break; + + case MAILMIME_MESSAGE: + + if (mime->mm_data.mm_message.mm_fields != NULL) { + struct mailimf_fields * fields; + + if (msg_info != NULL) { + fields = fetch_fields(msg_info, mime); + if (fields == NULL) { + res = ERROR_FETCH; + goto err; + } + + col = 0; + r = mailimf_fields_write(f, &col, fields); + if (r != NO_ERROR) { + mailimf_fields_free(fields); + res = r; + goto err; + } + + mailimf_fields_free(fields); + } + else { + col = 0; + r = fields_write(f, &col, mime->mm_data.mm_message.mm_fields); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + r = fprintf(f, "\r\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + r = etpan_render_mime(f, msg_info, + mime->mm_data.mm_message.mm_msg_mime); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + break; + } + + return NO_ERROR; + + err: + return res; +} + + + +int main(void) +{ + struct mailstorage * storage; + int r; + + storage = mailstorage_new(NULL); + + imap_mailstorage_init(storage, "imap.my-servers.org", 0, + NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN, + "my-login", "my-password", 1, "/home/login/.libetpan/cache"); + + r = mailstorage_connect(storage); + if (r == MAIL_NO_ERROR) { + struct mailfolder * folder; + + folder = mailfolder_new(storage, "INBOX", NULL); + + r = mailfolder_connect(folder); + if (r == MAIL_NO_ERROR) { + struct mailmessage_list * msg_list; + mailmessage * msg; + + mailfolder_get_messages_list(folder, &msg_list); + + if (carray_count(msg_list->msg_tab) > 0) { + struct mailmime * mime; + + msg = carray_get(msg_list->msg_tab, 0); + + mailmessage_get_bodystructure(msg, &mime); + + recursive_fetch(msg, mime); + + /* do the things */ + + mailmessage_flush(msg); + } + mailmessage_list_free(msg_list); + + mailfolder_disconnect(folder); + } + + mailstorage_disconnect(storage); + } + + mailstorage_free(storage); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AEN3472" +>Session</A +></H2 +><DIV +CLASS="SECT2" +><H3 +CLASS="SECT2" +><A +NAME="MAILSESSION-DRIVER" +>Session driver</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailsession_driver { + char * sess_name; + + int (* sess_initialize)(mailsession * session); + void (* sess_uninitialize)(mailsession * session); + + int (* sess_parameters)(mailsession * session, + int id, void * value); + + int (* sess_connect_stream)(mailsession * session, mailstream * s); + int (* sess_connect_path)(mailsession * session, char * path); + + int (* sess_starttls)(mailsession * session); + + int (* sess_login)(mailsession * session, char * userid, char * password); + int (* sess_logout)(mailsession * session); + int (* sess_noop)(mailsession * session); + + /* folders operations */ + + int (* sess_build_folder_name)(mailsession * session, char * mb, + char * name, char ** result); + + int (* sess_create_folder)(mailsession * session, char * mb); + int (* sess_delete_folder)(mailsession * session, char * mb); + int (* sess_rename_folder)(mailsession * session, char * mb, + char * new_name); + int (* sess_check_folder)(mailsession * session); + int (* sess_examine_folder)(mailsession * session, char * mb); + int (* sess_select_folder)(mailsession * session, char * mb); + int (* sess_expunge_folder)(mailsession * session); + int (* sess_status_folder)(mailsession * session, char * mb, + uint32_t * result_num, uint32_t * result_recent, + uint32_t * result_unseen); + int (* sess_messages_number)(mailsession * session, char * mb, + uint32_t * result); + int (* sess_recent_number)(mailsession * session, char * mb, + uint32_t * result); + int (* sess_unseen_number)(mailsession * session, char * mb, + uint32_t * result); + + int (* sess_list_folders)(mailsession * session, char * mb, + struct mail_list ** result); + int (* sess_lsub_folders)(mailsession * session, char * mb, + struct mail_list ** result); + + int (* sess_subscribe_folder)(mailsession * session, char * mb); + int (* sess_unsubscribe_folder)(mailsession * session, char * mb); + + /* messages operations */ + + int (* sess_append_message)(mailsession * session, + char * message, size_t size); + int (* sess_copy_message)(mailsession * session, + uint32_t num, char * mb); + int (* sess_move_message)(mailsession * session, + uint32_t num, char * mb); + + int (* sess_get_message)(mailsession * session, + uint32_t num, mailmessage ** result); + + int (* sess_get_message_by_uid)(mailsession * session, + const char * uid, mailmessage ** result); + + int (* sess_get_messages_list)(mailsession * session, + struct mailmessage_list ** result); + int (* sess_get_envelopes_list)(mailsession * session, + struct mailmessage_list * env_list); + int (* sess_remove_message)(mailsession * session, uint32_t num); +}; + </PRE +><P +> This is a driver for a session. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>sess_name</B +> is the name of the driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_initialize()</B +> is the function + that will initializes a data structure (field + <B +CLASS="COMMAND" +>sess_data</B +> in the session) specific to + the driver. + The field data (field <B +CLASS="COMMAND" +>sess_data</B +> in + the session) is the state of the session, + the internal data structure used by the driver. + It is called when creating the + <B +CLASS="COMMAND" +>mailsession</B +> structure with + <B +CLASS="COMMAND" +>mailsession_new()</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_uninitialize()</B +> frees the structure + created with <B +CLASS="COMMAND" +>sess_initialize()</B +> + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_parameters()</B +> implements + functions specific to the given mail access. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_connect_stream()</B +> connects a + stream to the session. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_connect_path()</B +> notify a main + path to the session. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_starttls()</B +> changes the current + stream to a TLS stream + (see <A +HREF="#MAILSTREAM-SSL" +>the Section called <I +>TLS stream</I +> in Chapter 2</A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_login()</B +> notifies the user and + the password to authenticate to the session. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_logout()</B +> exits the session and + closes the stream. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_noop()</B +> does no operation on the + session, but it can be used to poll for the status of + the connection. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_build_folder_name()</B +> will return an + allocated string with that contains the complete path of + the folder to create. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_create_folder()</B +> creates the + folder that corresponds to the given name. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_delete_folder()</B +> deletes the folder + that corresponds to the given name. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_rename_folder()</B +> change the name + of the folder. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_check_folder()</B +> makes a + checkpoint of the session. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_examine_folder()</B +> selects a mailbox as + readonly. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_select_folder()</B +> selects a mailbox. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_expunge_folder()</B +> deletes all + messages marked \Deleted. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_status_folder()</B +> queries the + status of the folder (number of messages, number of + recent messages, number of unseen messages). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_messages_number()</B +> queries the + number of messages in the folder. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_recent_number()</B +> queries the + number of recent messages in the folder. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_unseen_number()</B +> queries the number of + unseen messages in the folder. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_list_folders()</B +> returns the list of + all sub-mailboxes of the given mailbox. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_lsub_folders()</B +> returns the list of + subscribed sub-mailboxes of the given mailbox. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_subscribe_folder()</B +> subscribes to + the given mailbox. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_unsubscribe_folder()</B +> unsubscribes to + the given mailbox. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_append_message()</B +> adds a RFC 2822 + message to the current given mailbox. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_copy_message()</B +> copies a message + whose number is given to a given mailbox. The mailbox + must be accessible from the same session. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_move_message()</B +> moves a message whose + number is given to + a given mailbox. The mailbox must be accessible from the + same session. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_get_messages_list()</B +> returns the list + of message numbers + of the current mailbox + (see <A +HREF="#MAILMESSAGE-LIST" +>the Section called <I +>Message list</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_get_envelopes_list()</B +> fills the parsed + fields in the <B +CLASS="COMMAND" +>mailmessage</B +> structures + (see <A +HREF="#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>) + of the <B +CLASS="COMMAND" +>mailmessage_list</B +> + (see <A +HREF="#MAILMESSAGE-LIST" +>the Section called <I +>Message list</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_remove_message()</B +> removes the given + message from the mailbox. + The message is permanently deleted. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_get_message()</B +> returns a + mailmessage structure + (see <A +HREF="#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>) + that corresponds + to the given message number. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_get_message_by_uid()</B +> returns a + mailmessage structure + (see <A +HREF="#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>) + that corresponds + to the given message unique identifier. + </P +></LI +></UL +><P +> mandatory functions are the following : + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>sess_connect_stream()</B +> or + <B +CLASS="COMMAND" +>connect_path()</B +> + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_logout()</B +> + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_get_messages_list()</B +> + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_get_envelopes_list()</B +> + </P +></LI +></UL +><P +> we advise you to implement these functions : + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>sess_select_folder()</B +> (in case a session + can access several folders). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_noop()</B +> (to check if the server is + responding) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_check_folder()</B +> (to make a checkpoint + of the session) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_status_folder()</B +>, + <B +CLASS="COMMAND" +>sess_messages_number()</B +>, + <B +CLASS="COMMAND" +>sess_recent_number()</B +>, + <B +CLASS="COMMAND" +>sess_unseen_number()</B +> + (to get stat of the folder) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_append_message()</B +> (but can't be done + in the case of POP3 at least). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_login()</B +> in a case of an + authenticated driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_starttls()</B +> in a case of a stream + driver, if the procotol supports STARTTLS. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_get_message_by_uid()</B +> so that the + application can remember the messages + by UID and build its own list of messages. + </P +></LI +><LI +><P +> Everything that is specific to the driver will be + implemented in <B +CLASS="COMMAND" +>sess_parameters()</B +>. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="MAILSESSION" +>Session</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailsession { + void * sess_data; + mailsession_driver * sess_driver; +}; + +mailsession * mailsession_new(mailsession_driver * sess_driver); + +void mailsession_free(mailsession * session); + </PRE +><P +> This is a session. This is an abstraction used to access the + storage, using the network or the filesystem. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>sess_data</B +> is the state of the + session. This is specific to the driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_driver</B +> is the driver of the + session. + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailsession_new()</B +> will create a new session + using the given driver (<B +CLASS="COMMAND" +>sess_driver</B +>). + </P +><P +> <B +CLASS="COMMAND" +>mailsession_free()</B +> will release the memory + used by the session. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3670" +>mailsession_parameters</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_parameters(mailsession * session, + int id, void * value); + </PRE +><P +> This function make calls specific to the driver + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3674" +>mailsession_connect_stream</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_connect_stream(mailsession * session, mailstream * s); + </PRE +><P +> There are drivers of two kinds : stream drivers (driver that + connects to servers through TCP or other means of connection) + and file drivers (driver that are based on filesystem) + + This function can only be used by stream drivers and + this connects a stream to the session + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3678" +>mailsession_connect_path</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_connect_path(mailsession * session, char * path); + </PRE +><P +> This function can only be used by file drivers and + selects the main path of the session. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3682" +>mailsession_starttls</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_starttls(mailsession * session); + </PRE +><P +> This switches the current connection to TLS (secure layer). + This will only work with stream drivers. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3686" +>mailsession_login</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_login(mailsession * session, + char * userid, char * password); + </PRE +><P +> This notifies the login and the password to authenticate + to the session. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3690" +>mailsession_logout</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_logout(mailsession * session); + </PRE +><P +> This function disconnects the session and closes the stream. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3694" +>mailsession_noop</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_noop(mailsession * session); + </PRE +><P +> This function does no operation on the session, but it can be + used to poll for the status of the connection. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3698" +>mailsession_check_folder</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_check_folder(mailsession * session); + </PRE +><P +> This function makes a checkpoint of the session. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3702" +>mailsession_select_folder</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_select_folder(mailsession * session, char * mb); + </PRE +><P +> This function selects a mailbox. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3706" +>mailsession_expunge_folder</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_expunge_folder(mailsession * session); + </PRE +><P +> This function deletes all messages marked for deletion. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3710" +>mailsession_status_folder</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + </PRE +><P +> This function queries the status of the folder + (number of messages, number of recent messages, number of + unseen messages). + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3714" +>mailsession_messages_number</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_messages_number(mailsession * session, char * mb, + uint32_t * result); + </PRE +><P +> This function queries the number of messages in the folder. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3718" +>mailsession_recent_number</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_recent_number(mailsession * session, + char * mb, uint32_t * result); + </PRE +><P +> This function queries the number of recent messages in the + folder. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3722" +>mailsession_unseen_number</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_unseen_number(mailsession * session, char * mb, + uint32_t * result); + </PRE +><P +> This function queries the number of unseen messages in the + folder. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3726" +>mailsession_append_message</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_append_message(mailsession * session, + char * message, size_t size); + </PRE +><P +> This adds a RFC 2822 message to the current mailbox. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3730" +>mailsession_get_messages_list</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + </PRE +><P +> This function returns the list of messages + of the current mailbox. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3734" +>mailsession_get_envelopes_list</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_get_envelopes_list(mailsession * session, + struct mailmessage_list * result); + </PRE +><P +> This function fills the parsed fields in the + <B +CLASS="COMMAND" +>mailmessage</B +> structures + (see <A +HREF="#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>) + of the mailmessage_list + (see <A +HREF="#MAILMESSAGE-LIST" +>the Section called <I +>Message list</I +></A +>). + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3741" +>mailsession_get_message</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + </PRE +><P +> This function returns a <B +CLASS="COMMAND" +>mailmessage</B +> + (see <A +HREF="#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>) structure that + corresponds to the given message number. + </P +><DIV +CLASS="WARNING" +><P +></P +><TABLE +CLASS="WARNING" +BORDER="1" +WIDTH="100%" +><TR +><TD +ALIGN="CENTER" +><B +>Warning</B +></TD +></TR +><TR +><TD +ALIGN="LEFT" +><P +> <B +CLASS="COMMAND" +>mailsession_get_message_by_uid()</B +> should + be used instead. + </P +></TD +></TR +></TABLE +></DIV +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="AEN3750" +>mailsession_get_message_by_uid</A +></H3 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + </PRE +><P +> This function returns a mailmessage structure + that corresponds to the given message unique identifier. + This is currently implemented only for cached drivers. + </P +><DIV +CLASS="WARNING" +><P +></P +><TABLE +CLASS="WARNING" +BORDER="1" +WIDTH="100%" +><TR +><TD +ALIGN="CENTER" +><B +>Warning</B +></TD +></TR +><TR +><TD +ALIGN="LEFT" +><P +> That deprecates the use of + <B +CLASS="COMMAND" +>mailsession_get_message()</B +>. + </P +></TD +></TR +></TABLE +></DIV +></DIV +></DIV +></DIV +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API.sgml ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API.sgml Wed Dec 20 15:28:56 2006 @@ -0,0 +1,15097 @@ +<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN"> + +<book id="libetpan-api"> + <bookinfo> + <date>2003-12-03</date> + <title>libEtPan! API</title> + <authorgroup> + <author> + <firstname>Viet Hoa</firstname> + <surname>DINH</surname> + </author> + </authorgroup> + <copyright> + <year>2003</year> + <holder>DINH Viet Hoa</holder> + </copyright> + </bookinfo> + <toc></toc> + + <!-- Introduction --> + <chapter> + <title>Introduction</title> + <para> + This document will describe the API of libEtPan! + </para> + </chapter> + + <!-- Tools --> + <chapter> + <title>Tools and datatypes</title> + + <para> + libEtPan! include a collection of datatypes such as lists, + arrays, hash tables and tools such as buffered I/O. + </para> + + <!-- Array --> + <sect1> + <title>Array</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +typedef struct carray_s carray; + </programlisting> + + <para> + <command>carray</command> is an array of pointers that will + resize automatically in case a new element is added. + </para> + + <para> + The <command>carray</command> is implemented with an array + <command>(void **)</command> that can be resized. An array has a + size: this is the number of elements that can be added before + the table is resized. It also has a count of elements: this is + the elements that exist in the array. + </para> + + <sect2 id="carray-new"> + <title>carray_new and carray_free</title> + + <programlisting role="C"> +carray * carray_new(unsigned int initsize); + +void carray_free(carray * array); + </programlisting> + + <para> + <command>carray_new()</command> creates a new array with an + initial size. The array is not resized until the number of + element reach the initial size. It returns + <command>NULL</command> in case of failure. + </para> + + <para> + <command>carray_free()</command> releases memory used by the + given array. + </para> + + <example> + <title>carray creation</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <stdlib.h> + +#define SIZE 50 + +int main(void) +{ + carray * a; + + a = carray_new(SIZE); + if (a == NULL) + exit(EXIT_FAILURE); + + /* do things here */ + + carray_free(a); + + exit(EXIT_SUCESS); +} + </programlisting> + </example> + </sect2> + + <sect2 id="carray-set-size"> + <title>carray_set_size</title> + + <programlisting role="C"> +int carray_set_size(carray * array, uint32_t new_size); + </programlisting> + + <para> + <command>carray_set_size()</command> sets the size of the + array. It returns <command>0</command> in case of success, + <command>-1</command> in case of failure. + </para> + + <example> + <title>preallocating carray</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <stdlib.h> + +#define SIZE 50 +#define NEWSIZE 200 + +int main(void) +{ + carray * a; + unsigned int i; + char p[500]; + + a = carray_new(SIZE); + if (a == NULL) + goto err; + + r = carray_set_size(NEWSIZE); + if (r < 0) + goto free; + + for(i = 0 ; i < NEWSIZE ; i ++) + carray_set(a, i, &p[i]); + + /* do things here */ + + carray_free(a); + + exit(EXIT_SUCESS); + + free: + carray_free(a); + err: + exit(EXIT_FAILURE); +} + </programlisting> + </example> + </sect2> + + <!-- carray_count, carray_add, carray_get and carray_set --> + <sect2 id="carray-count"> + <title>carray_count, carray_add, carray_get and carray_set</title> + + <programlisting role="C"> +int carray_count(carray); + +int carray_add(carray * array, void * data, unsigned int * index); + +void * carray_get(carray * array, unsigned int indx); + +void carray_set(carray * array, unsigned int indx, void * value); + </programlisting> + + <para> + <command>carray_count()</command> returns the number of + elements in the <command>carray</command>. + Complexity is O(1). + </para> + + <para> + <command>carray_add()</command>adds an element at the end of + the array. The <command>index</command> of the element is + returns in <command>(* index)</command> if + <command>index</command> is not <command>NULL</command>. It + returns <command>0</command> in case of success, + <command>-1</command> in case of failure. + Complexity is O(1). + </para> + + <para> + <command>carray_get()</command> returns the elements contained + at the given cell of the table. + Complexity is O(1). + </para> + + <para> + <command>carray_set()</command> replace the element at the + given index of table table with the given value. + Complexity is O(1). + </para> + + <example> + <title>carray access</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <string.h> + +#define SIZE 50 + +int main(void) +{ + carray * a; + int r; + + a = carray_new(SIZE); + if (a == NULL) + goto err; + + r = carray_add(a, "foo-bar-1", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-2", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-3", NULL); + if (r < 0) + goto free; + + for(i = 0 ; i < carray_count(a) ; i ++) { + char * str; + + str = carray_get(a, i); + if (strcmp("foo-bar-2", str) == 0) + carray_set(a, i, "foo-bar-2-replacement"); + + printf("%s\n", str); + } + + carray_free(a); + + exit(EXIT_SUCESS); + + free: + carray_free(a); + err: + exit(EXIT_FAILURE); +} + </programlisting> + </example> + + </sect2> + + <!-- carray_delete --> + <sect2 id="carray-delete"> + <title>carray_delete</title> + + <programlisting role="C"> +int carray_delete(carray * array, uint32_t indx); + +int carray_delete_slow(carray * array, uint32_t indx); + +int carray_delete_fast(carray * array, uint32_t indx); + </programlisting> + + <para> + <command>carray_delete()</command> removes an element of the + table. Order will not be garanteed. The returned result can + be ignored. + Complexity is O(1). + </para> + + <para> + <command>carray_delete_slow()</command> removes an element of + the table. Order will be garanteed. The returned result can + be ignored. + Complexity is O(n). + </para> + + <para> + <command>carray_delete_fast()</command> the element will just + be replaced with <command>NULL</command>. Order will be kept + but the number of elements will remains the same. The + returned result can be ignored. + Complexity is O(1). + </para> + + <example> + <title>deletion in carray</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +#define SIZE 50 + +carray * build_array(void) +{ + carray * a; + + a = carray_new(SIZE); + if (a == NULL) + goto err; + + r = carray_add(a, "foo-bar-1", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-2", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-3", NULL); + if (r < 0) + goto free; + + return a; + + free: + carray_free(a); + err: + exit(EXIT_FAILURE); +} + +void delete(carray * a) +{ + /* deleting foo-bar-1 */ + carray_delete(a, 0); + /* resulting size is 2, order of elements is undefined */ +} + +void delete_slow(carray * a) +{ + /* deleting foo-bar-1 */ + carray_delete_slow(a, 0); + /* resulting size is 2, order of elements is the same */ +} + +void delete_fast(carray * a) +{ + /* deleting foo-bar-1 */ + carray_delete_slow(a, 0); + /* + resulting size is 3, + order of elements is { NULL, foo-bar-2, foo-bar-3 } + */ +} + </programlisting> + </example> + </sect2> + + <!-- carray_data --> + <sect2 id="carray-data"> + <title>carray_data</title> + + <programlisting role="C"> +void ** carray_data(carray); + </programlisting> + + <para> + <command>carray_data</command>returns the table used for + implementation : + <command>(void **)</command>. + </para> + + </sect2> + + + </sect1> + + <!-- List --> + <sect1 id="clist"> + <title>List</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +typedef struct clist_s clist; + +typedef clistcell clistiter; + </programlisting> + + <para> + <command>clist()</command> is a list of cells. + Each cell of the list contains one element. This element is a + pointer. An iterator (<command>clistiter</command>) is a + pointer to an element of the list. With an iterator, we can + get the previous element of the list, the next element of the + list and the content of the element. + </para> + + <sect2 id="clist-new"> + <title>clist_new and clist_free</title> + + <programlisting role="C"> +clist * clist_new(void); + +void clist_free(clist *); + </programlisting> + + <para> + <command>clist_new()</command> allocates a new empty list and + returns it. + </para> + + <para> + <command>clist_free()</command> frees the entire list with + its cells. + </para> + + <example> + <title>clist creation</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + goto err; + + r = clist_append(list, "foo-bar"); + if (r < 0) + + clist_free(list); + + exit(EXIT_SUCCESS); + + free: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + </programlisting> + </example> + </sect2> + + <sect2 id="clist-count"> + <title>clist_isempty and clist_count</title> + + <programlisting role="C"> +int clist_isempty(clist *); + +int clist_count(clist *); + </programlisting> + + <para> + <command>clist_isempty()</command> returns 1 if the list is + empty, else it is 0. + Complexity is O(1). + </para> + + <para> + <command>clist_count()</command> returns the number of + elements in the list. + Complexity is O(1). + </para> + </sect2> + + <sect2 id="clist-begin"> + <title>running through clist</title> + + <programlisting role="C"> +clistiter * clist_begin(clist *); + +clistiter * clist_end(clist *); + +clistiter * clist_next(clistiter *); + +clistiter * clist_previous(clistiter *); + +void * clist_content(clistiter *); + +void * clist_nth_data(clist * lst, int index); + +clistiter * clist_nth(clist * lst, int index); + </programlisting> + + <para> + <command>clist_begin()</command> returns an iterator to the + first element of the list. + Complexity is O(1). + </para> + + <para> + <command>clist_end()</command> returns an iterator to the last + element of the list. + Complexity is O(1). + </para> + + <para> + <command>clist_next()</command> returns an iterator to the + next element of the list. + Complexity is O(1). + </para> + + <para> + <command>clist_previous()</command> returns an iterator to the + previous element of the list. + Complexity is O(1). + </para> + + <para> + <command>clist_content()</command> returns the element + contained in the cell pointed by the iterator in the list. + Complexity is O(1). + </para> + + <para> + <command>clist_nth()</command> returns an iterator on the + <command>index</command>-th element of the list. + Complexity is O(n). + </para> + + <para> + <command>clist_nth_data()</command> returns the index-th + element of the list. + Complexity is O(n). + </para> + + <example> + <title>displaying content of clist</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(void) +{ + clist * list; + clistiter * iter; + + list = build_string_list(); + if (list == NULL) + goto err; + + for(iter = clist_begin(list) ; iter != NULL ; iter = + clist_next(iter)) { + char * str; + + str = clist_content(iter); + printf("%s\n", str); + } + + clist_free(list); + + exit(EXIT_SUCCESS); + + free: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + </programlisting> + </example> + </sect2> + + + <sect2 id="clist-append"> + <title>clist modification</title> + + <programlisting role="C"> +int clist_prepend(clist *, void *); + +int clist_append(clist *, void *); + +int clist_insert_before(clist *, clistiter *, void *); + +int clist_insert_after(clist *, clistiter *, void *); + +clistiter * clist_delete(clist *, clistiter *); + </programlisting> + + <para> + <command>clist_prepend()</command> adds an element at the + beginning of the list. Returns 0 on sucess, -1 on error. + Complexity is O(1). + </para> + + <para> + <command>clist_append()</command> adds an element at the end + of the list. Returns 0 on sucess, -1 on error. + Complexity is O(1). + </para> + + <para> + <command>clist_insert_before()</command> adds an element + before the element pointed by the given iterator in the + list. Returns 0 on sucess, -1 on error. + Complexity is O(1). + </para> + + <para> + <command>clist_insert_after()</command> adds an element after + the element pointed by the given iterator in the list. + Returns 0 on sucess, -1 on error. + Complexity is O(1). + </para> + + <para> + <command>clist_delete()</command> the elements pointed by + the given iterator in the list and returns an iterator to + the next element of the list. + Complexity is O(1). + </para> + + <example> + <title>deleting elements in a clist</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +voir print_content(void * content, void * user_data) +{ + char * str; + + str = content; + + printf("%s\n", str); +} + +int main(void) +{ + clist * list; + clistiter * iter; + + list = build_string_list(); + if (list == NULL) + goto err; + + iter = = clist_begin(list); + while (iter != NULL) + char * str; + + str = clist_content(iter); + if (strcmp(str, "foo-bar") == 0) + iter = clist_delete(list, cur); + else + iter = clist_next(iter); + } + + clist_foreach(list, print_content, NULL); + printf("\n"); + + clist_free(list); + + exit(EXIT_SUCCESS); + + free: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + </programlisting> + </example> + </sect2> + + <sect2 id="clist-foreach"> + <title>clist_foreach</title> + + <programlisting role="C"> +typedef void (* clist_func)(void *, void *); + +void clist_foreach(clist * lst, clist_func func, void * data); + </programlisting> + + <para> + <command>clist_foreach()</command> apply a fonction to each + element of the list. + Complexity is O(n). + </para> + </sect2> + + <sect2 id="clist-concat"> + <title>clist_concat</title> + + <programlisting role="C"> +void clist_concat(clist * dest, clist * src); + </programlisting> + + <para> + <command>clist_concat()</command> adds all the elements of src + at the end of dest. Elements are added in the same + order. src is an empty list when the operation is finished. + Complexity is O(1). + </para> + + <example> + <title>merging two clists</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(void) +{ + clist * list; + clist * list_2; + clistiter * iter; + + list = build_string_list(); + if (list == NULL) + goto err; + + list_2 = build_string_list_2(); + if (list == NULL) + goto free_list; + + clist_concat(list, list_2); + clist_free(list_2); + + for(iter = clist_begin(list) ; iter != NULL ; iter = + clist_next(iter)) { + char * str; + + str = clist_content(iter); + printf("%s\n", str); + } + + clist_free(list); + + exit(EXIT_SUCCESS); + + free_list: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + </programlisting> + </example> + + </sect2> + </sect1> + + <!-- Hash --> + <sect1> + <title>Hash table</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +typedef struct chash chash; + +typedef struct chashcell chashiter; + +typedef struct { + char * data; + int len; +} chashdatum; + </programlisting> + + <para> + <command>chash</command> is a hash table. + <command>chashiter</command> is a pointer to an element of the + hash table. + <command>chashdatum</command> is an element to be placed in + the hash table as a key or a value. It consists in + data and a corresponding length. + </para> + + <sect2 id="chash-new"> + <title>chash_new and chash_free</title> + <programlisting role="C"> +#define CHASH_COPYNONE 0 +#define CHASH_COPYKEY 1 +#define CHASH_COPYVALUE 2 +#define CHASH_COPYALL (CHASH_COPYKEY | CHASH_COPYVALUE) + +chash * chash_new(int size, int flags); + +void chash_free(chash * hash); + </programlisting> + + <para> + <command>chash_new()</command> returns a new empty hash table + or <command>NULL</command> if this + failed. <command>size</command> is the initial size of the + table used for implementation. <command>flags</command> can + be a combinaison of <command>CHASH_COPYKEY</command> and + <command>CHASH_COPYVALUE</command>. + <command>CHASH_COPYKEY</command> enables copy of key, so + that the initial value used for <command>chash_set()</command> + </para> + + <para> + <command>chash_free()</command> releases memory used by the + hash table. + </para> + </sect2> + + <sect2 id="chash-get"> + <title>chash_set and chash_get</title> + <programlisting role="C"> +int chash_set(chash * hash, + chashdatum * key, chashdatum * value, chashdatum * oldvalue); + +int chash_get(chash * hash, + chashdatum * key, chashdatum * result); + </programlisting> + + <para> + <command>chash_set()</command> adds a new element into the + hash table. If a previous element had the same key, it is + returns into oldvalue if <command>oldvalue</command> is + different of NULL. + Medium complexity is O(1). + </para> + + <para> + returns -1 if it fails, 0 on success. + </para> + + <para> + <command>chash_get()</command>returns the corresponding value + of the given key. If there is no corresponding value, -1 is + returned. 0 on success. + Medium complexity is O(1). + </para> + + <example> + <title>chash insert and lookup</title> + <programlisting role="C"> +int main(void) +{ + chash * hash; + int r; + chashdatum key; + chashdatum value; + char * str1 = "my-data"; + char * str2 = "my-data"; + + hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE); + + key.data = "foo"; + key.len = strlen("foo"); + value.data = str1; + value.data = strlen(str1) + 1; + /* + 1 is needed to get the terminal zero in the returned string */ + r = chash_set(hash, &key, &value, NULL); + if (r < 0) + goto free_hash; + + key.data = "bar"; + key.len = strlen("bar"); + value.data = str2; + value.data = strlen(str2) + 1; + if (r < 0) + goto free_hash; + + key.data = "foo"; + key.len = strlen("foo"); + r = chash_get(hash, &key, &value); + if (r < 0) { + printf("element not found\n"); + } + else { + char * str; + + str = value.data; + printf("found : %s", str); + } + + chash_free(hash); + + exit(EXIT_SUCCESS); + + free_hash: + chash_free(hash); + err: + exit(EXIT_FAILURE); +} + </programlisting> + </example> + </sect2> + + <sect2 id="chash-delete"> + <title>chash_delete</title> + <programlisting role="C"> +int chash_delete(chash * hash, + chashdatum * key, chashdatum * oldvalue); + </programlisting> + + <para> + deletes the key/value pair given the corresponding key. + The value is returned in old_value. + If there is no corresponding value, -1 is returned. 0 on success. + Medium complexity is O(1). + </para> + + <example> + <title>key deletion in a chash</title> + <programlisting role="C"> +int main(void) +{ + chash * hash; + int r; + chashdatum key; + chashdatum value; + char * str1 = "my-data"; + char * str2 = "my-data"; + + hash = build_hash(); + + key.data = "foo"; + key.len = strlen("foo"); + chash_delete(hash, &key, &value); + + /* it will never be possible to lookup "foo" */ + key.data = "foo"; + key.len = strlen("foo"); + r = chash_get(hash, &key, &value); + if (r < 0) { + printf("element not found\n"); + } + else { + char * str; + + str = value.data; + printf("found : %s", str); + } + + chash_free(hash); + + exit(EXIT_SUCCESS); + + free_hash: + chash_free(hash); + err: + exit(EXIT_FAILURE); +} + </programlisting> + </example> + </sect2> + + <sect2 id="chash-resize"> + <title>chash_resize</title> + <programlisting role="C"> +int chash_resize(chash * hash, int size); + </programlisting> + + <para> + <command>chash_resize()</command> changes the size of the + table used for implementation of the hash table. + returns 0 on success, -1 on failure. + </para> + </sect2> + + <sect2 id="chash-begin"> + <title>running through the chash</title> + <programlisting role="C"> +chashiter * chash_begin(chash * hash); + +chashiter * chash_next(chash * hash, chashiter * iter); + +void chash_key(chashiter * iter, chashdatum * result); + +void chash_value(chashiter iter, chashdatum * result); + </programlisting> + + <para> + <command>chash_begin()</command> returns a pointer to the + first element of the hash table. Returns + <command>NULL</command> if there is no elements in the hash + table. + Complexity is O(n). + </para> + + <para> + <command>chash_next()</command> returns a pointer to the next + element of the hash table. Returns <command>NULL</command> + if there is no next element. + Complexity is O(n) but n calls to chash_next() also has + a complexity of O(n). + </para> + + <para> + <command>chash_key()</command> returns the key of the given + element of the hash table. + </para> + + <para> + <command>chash_value</command> returns the value of the + given element of the hash table. + </para> + + <example> + <title>running through a chash</title> + <programlisting role="C"> +int main(void) +{ + chash * hash; + int r; + chashiter * iter; + + hash = build_hash(); + + /* this will display all the values stored in the hash */ + for(iter = chash_begin(hash) ; iter != NULL ; iter = + chash_next(hash, iter)) { + chashdatum key; + chashdatum value; + char * str; + + chash_value(iter, &value); + str = value.data; + printf("%s\n", str); + } + + chash_free(hash); +} + </programlisting> + </example> + </sect2> + + <sect2 id="chash-count"> + <title>chash_size and chash_count</title> + <programlisting role="C"> +int chash_size(chash * hash); + +int chash_count(chash * hash); + </programlisting> + + <para> + <command>chash_size()</command> returns the size of the table + used for implementation of the hash table. + Complexity is O(1). + </para> + + <para> + <command>chash_count()</command> returns the number of + elements in the hash table. + Complexity is O(1). + </para> + </sect2> + </sect1> + + <!-- mailstream --> + <sect1> + <title>Buffered I/O</title> + +<programlisting role="C"> +#include <libetpan/libetpan.h> + +typedef struct _mailstream mailstream; + </programlisting> + + <para> + streams are objects where we can read data from and write data + to. They are not seekable. That can be for example a pipe or a + network stream. + </para> + + <programlisting role="C"> +mailstream * mailstream_new(mailstream_low * low, size_t buffer_size); + +int mailstream_close(mailstream * s); + </programlisting> + + <para> + <command>mailstream_new()</command> creates a new stream + stream with the low-level (see <xref linkend="mailstream-low">) + stream and a given buffer size. + </para> + + <para> + <command>mailstream_close()</command> closes the stream. + This function will be in charge to free the + <command>mailstream_low</command> structure. + </para> + + + <programlisting role="C"> +ssize_t mailstream_write(mailstream * s, void * buf, size_t count); + +int mailstream_flush(mailstream * s); + +ssize_t mailstream_read(mailstream * s, void * buf, size_t count); + +ssize_t mailstream_feed_read_buffer(mailstream * s); + </programlisting> + + <para> + <command>mailstream_write()</command> writes a buffer to the + given stream. This write operation will be buffered. + </para> + + <para> + <command>mailstream_flush()</command> will force a write of + all buffered data for a given stream. + </para> + + <para> + <command>mailstream_read()</command> reads data from the + stream to the given buffer. + </para> + + <para> + <command>mailstream_feed_read_buffer()</command> this function + will just fill the buffer for reading. + </para> + + <programlisting role="C"> +mailstream_low * mailstream_get_low(mailstream * s); + +void mailstream_set_low(mailstream * s, mailstream_low * low); + </programlisting> + + <para> + <command>mailstream_get_low()</command> returns the low-level + stream of the given stream. + </para> + + <para> + <command>mailstream_set_low()</command> changes the low-level + of the given stream. Useful, for + example, when a stream change from clear stream to SSL + stream. + </para> + + <programlisting role="C"> +char * mailstream_read_line(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_append(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line); + +char * mailstream_read_multiline(mailstream * s, size_t size, + MMAPString * stream_buffer, + MMAPString * multiline_buffer, + size_t progr_rate, + progress_function * progr_fun); + </programlisting> + + <para> + <command>mailstream_read_line()</command> reads an entire line + from the buffer and store it into the + given string. returns <command>NULL</command> on error, the + corresponding array + of <command>char</command> is returned otherwise. + </para> + + <para> + <command>mailstream_read_line_append()</command> reads an entire + line from the buffer and appends it to the + given string. returns <command>NULL</command> on error, the + array of char corresponding to the entire buffer is returned + otherwise. + </para> + + <para> + <command>mailstream_read_line_remove_eol()</command> reads an + entire line from the buffer and store it into the + given string. All CR LF are removed. + returns <command>NULL</command> on error, the corresponding + array of <command>char</command> is returned otherwise. + </para> + + <para> + <command>mailstream_read_multiline()</command> reads a + multiline data (several lines, the data are ended with + a single period '.') + from the given stream and store it into the given + multiline buffer (multiline_buffer). progr_rate should be 0 + and progr_fun <command>NULL</command> (deprecated things). + <command>stream_buffer</command> is a buffer used for internal + work of the function. + size should be 0 (deprecated things). + </para> + + <programlisting role="C"> +int mailstream_is_end_multiline(char * line); + </programlisting> + + <para> + returns 1 if the line is an end of multiline data (a single + period '.', eventually with CR and/or LF). 0 is returned + otherwise. + </para> + + <programlisting role="C"> +int mailstream_send_data(mailstream * s, char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun); + </programlisting> + + <para> + sends multiline data to the given stream. + <command>size</command> is the size of the data. + <command>progr_rate</command> and <command>progr_fun</command> + are deprecated. <command>progr_rate</command> must be 0, + <command>progr_fun</command> must be NULL. + </para> + + <sect2 id="mailstream-socket"> + <title>socket stream</title> + + <programlisting role="C"> +mailstream * mailstream_socket_open(int fd); + </programlisting> + + <para> + <command>mailstream_socket_open()</command> will open a + clear-text socket. + </para> + </sect2> + + <sect2 id="mailstream-ssl"> + <title>TLS stream</title> + + <programlisting role="C"> +mailstream * mailstream_ssl_open(int fd); + </programlisting> + + <para> + <command>mailstream_ssl_open()</command> will open a + TLS/SSL socket. + </para> + </sect2> + </sect1> + + <!-- mailstream_low --> + <sect1 id="mailstream-low"> + <title>non-buffered I/O</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailstream_low_driver { + ssize_t (* mailstream_read)(mailstream_low *, void *, size_t); + ssize_t (* mailstream_write)(mailstream_low *, void *, size_t); + int (* mailstream_close)(mailstream_low *); + int (* mailstream_get_fd)(mailstream_low *); + void (* mailstream_free)(mailstream_low *); +}; + +typedef struct mailstream_low_driver mailstream_low_driver; + +struct _mailstream_low { + void * data; + mailstream_low_driver * driver; +}; + </programlisting> + + <para> + <command>mailstream_low</command> is a non-buffered stream. + </para> + + <para> + The <command>mailstream_low_driver</command> is a set of + functions used to access the stream. + </para> + + <itemizedlist> + <listitem> + <para> + <command>mailstream_read/write/close()</command> is the same + interface as <command>read/write/close()</command> + system calls, except that the file descriptor is replaced with the + <command>mailstream_low</command> structure. + </para> + </listitem> + <listitem> + <para> + <command>mailstream_get_fd()</command> returns the file + descriptor used for this non-buffered stream. + </para> + </listitem> + <listitem> + <para> + <command>mailstream_free()</command> is in charge to free + the internal structure of the mailstream_low and the + mailstream_low itself. + </para> + </listitem> + </itemizedlist> + + <programlisting role="C"> +mailstream_low * mailstream_low_new(void * data, + mailstream_low_driver * driver); + </programlisting> + + <para> + mailstream_low_new() creates a low-level mailstream with the + given internal structure (data) and using the given set of + functions (driver). + </para> + + <programlisting role="C"> +ssize_t mailstream_low_write(mailstream_low * s, void * buf, size_t count); + +ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count); + +int mailstream_low_close(mailstream_low * s); + +int mailstream_low_get_fd(mailstream_low * s); + +void mailstream_low_free(mailstream_low * s); + </programlisting> + + <para> + Each of these calls will call the corresponding function defined + in the driver. + </para> + + </sect1> + + + <!-- MMAPString --> + <sect1> + <title>strings</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct _MMAPString +{ + char * str; + size_t len; + size_t allocated_len; + int fd; + size_t mmapped_size; +}; + +typedef struct _MMAPString MMAPString; + </programlisting> + + <para> + MMAPString is a string which size that can increase automatically. + </para> + + <sect2 id="mmap-string-new"> + <title>constructor and destructor</title> + <programlisting role="C"> +MMAPString * mmap_string_new(const char * init); + +MMAPString * mmap_string_new_len(const char * init, size_t len); + +MMAPString * mmap_string_sized_new(size_t dfl_size); + +void mmap_string_free(MMAPString * string); + </programlisting> + + <para> + <command>mmap_string_new()</command> allocates a new + string. init is the intial value of the string. + <command>NULL</command> will be returned on error. + </para> + + <para> + <command>mmap_string_new_len()</command> allocates a new + string. init is the intial value of the + string, len is the length of the initial string. + <command>NULL</command> will be returned on error. + </para> + + <para> + <command>mmap_string_sized_new()</command> allocates a new + string. dfl_size is the initial allocation of + the string. <command>NULL</command> will be returned on error. + </para> + + <para> + <command>mmap_string_free()</command> release the memory used + by the string. + </para> + </sect2> + + <sect2 id="mmap-string-assign"> + <title>string value modification</title> + <programlisting role="C"> +MMAPString * mmap_string_assign(MMAPString * string, const char * rval); + +MMAPString * mmap_string_truncate(MMAPString *string, size_t len); + </programlisting> + + <para> + <command>mmap_string_assign()</command> sets a new value for + the given string. + <command>NULL</command> will be returned on error. + </para> + + <para> + <command>mmap_string_truncate()</command> sets a length for + the string. + <command>NULL</command> will be returned on error. + </para> + + <programlisting role="C"> +MMAPString * mmap_string_set_size (MMAPString * string, size_t len); + </programlisting> + + <para> + sets the allocation of the string. + <command>NULL</command> will be returned on error. + </para> + </sect2> + + <sect2 id="mmap-string-append"> + <title>insertion in string, deletion in string</title> + <programlisting role="C"> +MMAPString * mmap_string_insert_len(MMAPString * string, size_t pos, + const char * val, size_t len); + +MMAPString * mmap_string_append(MMAPString * string, const char * val); + +MMAPString * mmap_string_append_len(MMAPString * string, + const char * val, size_t len); + +MMAPString * mmap_string_append_c(MMAPString * string, char c); + +MMAPString * mmap_string_prepend(MMAPString * string, const char * val); + +MMAPString * mmap_string_prepend_c(MMAPString * string, char c); + +MMAPString * mmap_string_prepend_len(MMAPString * string, const char * val, + size_t len); + +MMAPString * mmap_string_insert(MMAPString * string, size_t pos, + const char * val); + +MMAPString * mmap_string_insert_c(MMAPString *string, size_t pos, + char c); + +MMAPString * mmap_string_erase(MMAPString * string, size_t pos, + size_t len); + </programlisting> + + <para> + For complexity here, n is the size of the given MMAPString, + and len is the size of the string to insert. + </para> + + <para> + <command>mmap_string_insert_len()</command> inserts the given + string value of given length in the string at the given + position. <command>NULL</command> will be returned on error. + Complexity is O(n + len). + </para> + + <para> + <command>mmap_string_append()</command> appends the given + string value at the end of the string. + <command>NULL</command> will be returned on error. + Complexity is O(len). + </para> + + <para> + <command>mmap_string_append_len()</command> appends the + given string value of given length at the end of the + string. <command>NULL</command> will be returned on error. + Complexity is O(len). + </para> + + <para> + <command>mmap_string_append_c()</command> appends the given + character at the end of the string. + <command>NULL</command> will be returned on error. + Complexity is O(1). + </para> + + <para> + <command>mmap_string_prepend()</command> insert the given + string value at the beginning of the string. + <command>NULL</command> will be returned on error. + Complexity is O(n + len). + </para> + + <para> + <command>mmap_string_prepend_c()</command> insert the given + character at the beginning of the string. + <command>NULL</command> will be returned on error. + Complexity is O(n). + </para> + + <para> + <command>mmap_string_prepend_len()</command> insert the given + string value of given length at the beginning of the string. + <command>NULL</command> will be returned on error. + Complexity is O(n + len). + </para> + + <para> + <command>mmap_string_insert()</command> inserts the given + string value in the string at the given position. + NULL will be returned on error. + Complexity is O(n + len). + </para> + + <para> + <command>mmap_string_insert_c()</command> inserts the given + character in the string at the given position. + NULL will be returned on error. + Complexity is O(n). + </para> + + <para> + <command>mmap_string_erase()</command> removes the given + count of characters (len) at the given position of the + string. <command>NULL</command> will be returned on error. + Complexity is O(n). + </para> + + </sect2> + + <sect2 id="mmap-string-ref"> + <title>referencing string</title> + <programlisting role="C"> +int mmap_string_ref(MMAPString * string); + +int mmap_string_unref(char * str); + </programlisting> + + <para> + MMAPString provides a mechanism that let you use MMAPString + like normal strings. You have first to use + <command>mmap_string_ref()</command>, so that you notify + that the string will be used as a normal string, then, you + use <command>mmapstr->str</command> to refer to the + string. When you have finished and you want to free a string + corresponding to a <command>MMAPString</command>, you will + use <command>mmap_string_unref</command>. + </para> + + <para> + <command>mmap_string_ref()</command> references the string + so that the array of characters can be used as a normal + string then released with + <command>mmap_string_unref()</command>. + The array of characters will be obtained with string->str. + returns -1 on error, 0 on success. + </para> + </sect2> + </sect1> + </chapter> + + <!-- IMF --> + <chapter id="imf"> + <title>Internet Message Format</title> + + <para> + libEtPan! implements Internet Message parser. Currently, format + is RFC 2822. + This module also allows to generate messages. + </para> + + <warning> + <para> + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + </para> + + <para> + allocation functions will return <command>NULL</command> on failure + + functions returning integer will be returning one of the + following error code: + <command>MAILIMF_NO_ERROR</command>, + <command>MAILIMF_ERROR_PARSE</command>, + <command>MAILIMF_ERROR_MEMORY</command>, + <command>MAILIMF_ERROR_INVAL</command>, + or <command>MAILIMF_ERROR_FILE</command>. + </para> + </warning> + + <sect1> + <title>Quick start</title> + + <para> + You will need this module when you want to parse headers + of messages or when you want to build message headers + conformant to standards. + </para> + + <sect2> + <title>Parse message headers</title> + <para> + You will use one of the four following functions, depending + on your needs : + </para> + <itemizedlist> + <listitem> + <para> + <command>mailimf_envelope_and_optional_fields_parse</command> + (<xref linkend="mailimf-envelope-and-optional-fields-parse">), + </para> + </listitem> + <listitem> + <para> + <command>mailimf_envelope_fields_parse</command> + (<xref linkend="mailimf-envelope-fields-parse">), + </para> + </listitem> + <listitem> + <para> + <command>mailimf_optional_fields_parse</command> + (<xref linkend="mailimf-optional-fields-parse">), + </para> + </listitem> + <listitem> + <para> + <command>mailimf_fields_parse</command> + (<xref linkend="mailimf-fields-parse">). + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Render the message headers</title> + <para> + Build your message headers, then use + <command>mailimf_fields_write</command> + (<xref linkend="mailimf-fields-write">) + to render the headers. + </para> + </sect2> + </sect1> + + <sect1> + <title>Data types</title> + <!-- mailimf_mailbox --> + <sect2 id="mailimf-mailbox"> + <title>mailimf_mailbox - mailbox</title> + <para> +#include <libetpan/libetpan.h> + +struct mailimf_mailbox { + char * mb_display_name; /* can be NULL */ + char * mb_addr_spec; /* != NULL */ +}; + +struct mailimf_mailbox * +mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec); + +void mailimf_mailbox_free(struct mailimf_mailbox * mailbox); + </para> + + <para> + This is an email mailbox with a display name. + </para> + + <example> + <title>example of mailbox</title> + <programlisting> +DINH Viet Hoa <hoa@users.sourceforge.net> + </programlisting> + </example> + + <para> + <command>mailimf_mailbox_new</command> creates and + initializes a data structure with a value. + Strings given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_mailbox_free</command> frees memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>mailbox creation and display</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_mailbox * mb; + char * display_name; + char * address; + + display_name = strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="); + address = strdup("dinh.viet.hoa@free.fr"); + mb = mailimf_mailbox_new(str, address); + /* do the things */ + mailimf_mailbox_free(mb); + + return 0; +} + +/* display mailbox information */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_mailbox(struct mailimf_mailbox * mb) +{ + if (mb->mb_display_name != NULL) + printf("display name: %s\n", mb->mb_display_name); + printf("address specifier : %s\n", mb->mb_addr_spec); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_address --> + <sect2 id="mailimf-address"> + <title>mailimf_address - address</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_address { + int ad_type; + union { + struct mailimf_mailbox * ad_mailbox; /* can be NULL */ + struct mailimf_group * ad_group; /* can be NULL */ + } ad_data; +}; + +struct mailimf_address * +mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox, + struct mailimf_group * ad_group); + +void mailimf_address_free(struct mailimf_address * address); + </programlisting> + + <para> + This is a mailbox or a group of mailbox. + </para> + + <itemizedlist> + <listitem> + <para> + <command>ad_type</command> can be MAILIMF_ADDRESS_MAILBOX or + <command>MAILIMF_ADDRESS_GROUP</command>. + </para> + </listitem> + <listitem> + <para> + <command>ad_data.ad_mailbox</command> is a mailbox if + <command>ad_type</command> is + <command>MAILIMF_ADDRESS_MAILBOX</command> + see <xref linkend="mailimf-mailbox">) + </para> + </listitem> + <listitem> + <para> + <command>ad_data.group</command> is a group if type is + <command>MAILIMF_ADDRESS_GROUP</command>. + see <xref linkend="mailimf-group">) + </para> + </listitem> + </itemizedlist> + + <para> + <command>mailimf_address_new()</command> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_address_free</command> frees memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>address creation and display</title> + <programlisting role="C"> +/* creates an address of type mailbox */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_address * a_mb; + struct mailimf_mailbox * mb; + char * display_name; + char * address; + + display_name = strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="); + address = strdup("dinh.viet.hoa@free.fr"); + mb = mailimf_mailbox_new(str, address); + + a_mb = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + /* do the things */ + mailimf_address_free(a_mb); +} + +/* creates an address of type group */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_address * a_g; + struct mailimf_group * g; + char * display_name; + + display_name = strdup("undisclosed-recipient"); + g = mailimf_group_new(display_name, NULL); + + a_g = mailimf_address_new(MAILIMF_ADDRESS_GROUP, NULL, g); + /* do the things */ + mailimf_address_free(a_g); + + return 0; +} + +/* display the content of an address */ + +#include <libetpan/libetpan.h> + +void display_address(struct mailimf_address * a) +{ + clistiter * cur; + + switch (a->ad_type) { + case MAILIMF_ADDRESS_GROUP: + display_mailimf_group(a->ad_data.ad_group); + break; + + case MAILIMF_ADDRESS_MAILBOX: + display_mailimf_mailbox(a->ad_data.ad_mailbox); + break; + } +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_mailbox_list --> + <sect2 id="mailimf-mailbox-list"> + <title>mailimf_mailbox_list - list of mailboxes</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_mailbox_list { + clist * mb_list; /* list of (struct mailimf_mailbox *), != NULL */ +}; + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new(clist * mb_list); + +void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list); + </programlisting> + + <para> + This is a list of mailboxes. + </para> + + <para> + <command>mb_list</command> is a list of mailboxes. This is a + <command>clist</command> which elements are of type + mailimf_mailbox (see <xref linkend="mailimf-mailbox">). + </para> + + <para> + <command>mailimf_mailbox_list_new()</command> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_mailbox_list_free()</command> frees memory used by the + structure and substructures will also be released. + </para> + + <example> + <title>Creation and display of mailimf_mailbox_list</title> + <programlisting role="C"> +/* creates a list of mailboxes with two mailboxes */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_group * g; + char * display_name; + struct mailimf_mailbox_list * mb_list; + clist * list; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + list = clist_append(mb); + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + list = clist_append(mb); + + mb_list = mailimf_mailbox_list_new(list); + /* do the things */ + mailimf_mailbox_list_free(mb_list); + + return 0; +} + +/* display a list of mailboxes */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_mailbox_list(struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + display_mailbox(mb); + printf("\n"); + } +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_address_list --> + <sect2 id="mailimf-address-list"> + <title>mailimf_address_list - list of addresses</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_address_list { + clist * ad_list; /* list of (struct mailimf_address *), != NULL */ +}; + +struct mailimf_address_list * +mailimf_address_list_new(clist * ad_list); + +void mailimf_address_list_free(struct mailimf_address_list * addr_list); + </programlisting> + + <para> + This is a list of addresses. + </para> + + <para> + <command>ad_list</command> is a list of addresses. This is a + <command>clist</command> which elements are + of type mailimf_address (see <xref linkend="mailimf-address">). + </para> + + <para> + <command>mailimf_address_list_new()</command> creates and + initializes a data structure with + a value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_address_list_free()</command> frees memory + used by the structure and substructures will also be released. + </para> + + <example> + <title>creation and display of list of addresses</title> + <programlisting role="C"> +/* creates a list of addresses with two addresses */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_address_list * addr_list; + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + list = clist_append(addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + list = clist_append(addr); + + addr_list = mailimf_address_list_new(list); + /* do the things */ + mailimf_address_list_free(mb_list); + + return 0; +} + +/* display a list of addresses */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_address_list(struct mailimf_address_list * addr_list) +{ + clistiter * cur; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + display_address(addr); + printf("\n"); + } +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_group --> + <sect2 id="mailimf-group"> + <title>mailimf_group - named group of mailboxes</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_group { + char * grp_display_name; /* != NULL */ + struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */ +}; + +struct mailimf_group * +mailimf_group_new(char * grp_display_name, + struct mailimf_mailbox_list * grp_mb_list); + +void mailimf_group_free(struct mailimf_group * group); + </programlisting> + + <para> + This is a list of mailboxes tagged with a name. + </para> + + <example> + <title>example of group</title> + <programlisting> + they play music: <steve@morse.foo>, <neal@morse.foo>, + <yngwie@malmsteen.bar>, <michael@romeo.bar>; + </programlisting> + </example> + + <para> + <command>grp_display_name</command> is the name that will be + displayed for this group, + for example '<command>group_name</command>' in + '<command>group_name: address1@domain1, + address2@domain2;</command>'. + This must be allocated with malloc(). + <command>grp_mb_list</command> is a list of mailboxes + (see <xref linkend="mailimf-mailbox-list">). + </para> + + <para> + <command>mailimf_group_new()</command> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_group_free()</command> frees memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>creation and display of a group</title> + <programlisting role="C"> +/* creates an empty group */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_group * g; + char * display_name; + + display_name = strdup("undisclosed-recipient"); + g = mailimf_group_new(display_name, NULL); + /* do the things */ + mailimf_group_free(g); +} + +/* creates a group with two mailboxes */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_group * g; + char * display_name; + struct mailimf_mailbox_list * mb_list; + struct mailimf_mailbox * mb; + clist * list; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + list = clist_append(mb); + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + list = clist_append(mb); + + mb_list = mailimf_mailbox_list_new(list); + + display_name = strdup("my_group"); + g = mailimf_group_new(display_name, mb_list); + /* do the things */ + mailimf_group_free(g); + + return 0; +} + +/* display content of group */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_group(struct mailimf_group * group) +{ + printf("name of the group: %s\n", a->group->display_name); + for(cur = clist_begin(a->group->mb_list->list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + display_mailbox(mb); + printf("\n"); + } +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_date_time --> + <sect2 id="mailimf-date-time"> + <title>mailimf_date_time - date of a message</title> + + <para> +#include <libetpan/libetpan.h> + +struct mailimf_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +struct mailimf_date_time * +mailimf_date_time_new(int dt_day, int dt_month, int dt_year, + int dt_hour, int dt_min, int dt_sec, int dt_zone); + +void mailimf_date_time_free(struct mailimf_date_time * date_time); + </para> + + <para> + This is the date and time of a message. + For example : + </para> + <example> + <title>example of date</title> + <programlisting> +Thu, 11 Dec 2003 00:15:02 +0100. + </programlisting> + </example> + + <itemizedlist> + <listitem> + <para> + <command>dt_day</command> is the day of month (1 to 31) + </para> + </listitem> + <listitem> + <para> + <command>dt_month</command> (1 to 12) + </para> + </listitem> + <listitem> + <para> + <command>dt_year</command> (4 digits) + </para> + </listitem> + <listitem> + <para> + <command>dt_hour</command> (0 to 23) + </para> + </listitem> + <listitem> + <para> + <command>dt_min</command> (0 to 59) + </para> + </listitem> + <listitem> + <para> + <command>dt_sec</command> (0 to 59) + </para> + </listitem> + <listitem> + <para> + <command>dt_zone</command> (this is the decimal value that + we can read, for example: for + '<command>-0200</command>', the value is + <command>-200</command>). + </para> + </listitem> + </itemizedlist> + + <para> + <command>mailimf_date_time_new()</command> creates and + initializes a date structure with a value. + </para> + + <para> + <command>mailimf_date_time_free()</command> frees memory used + by the structure. + </para> + + <example> + <title>creation and display of date</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_date_time * d; + + d = mailimf_date_time_new(9, 5, 2003, 3, 01, 40, -0200); + /* do the things */ + mailimf_date_time_free(d); + + return 0; +} + +/* display the date */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_date(struct mailimf_date_time * d) +{ + printf("%02i/%02i/%i %02i:%02i:%02i %+04i\n", + d->dt_day, d->dt_month, d->dt_year, + d->dt_hour, d->dt_min, d->dt_sec, d->dt_zone); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_orig_date --> + <sect2 id="mailimf-orig-date"> + <title>mailimf_orig_date - parsed content of date header</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_orig_date { + struct mailimf_date_time * dt_date_time; /* != NULL */ +}; + +struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time * + dt_date_time); + +void mailimf_orig_date_free(struct mailimf_orig_date * orig_date); + </programlisting> + + <para> + This is the content of a header <command>Date</command> or + <command>Resent-Date</command>. + It encapsulates a mailimf_date_time + </para> + + <para> + <command>dt_date_time</command> is the parsed date + (see <xref linkend="mailimf-date-time">). + </para> + + <para> + <command>mailimf_orig_date_new()</command> creates and + initializes a data structure with + a value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_orig_date_free()</command> frees memory used + by the structure and substructures will also be released. + </para> + + <example> + <title>creation and display of Date field</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_date_time * d; + struct mailimf_orig_date * date; + + d = mailimf_date_time_new(9, 5, 2003, 3, 01, 40, -0200); + date = mailimf_orig_date_new(d); + /* do the things */ + mailimf_orig_date_free(date); + + return 0; +} + +/* display date header */ + +#include <libetpan/libetpan.h> + +void display_orig_date(struct mailimf_orig_date * orig_date) +{ + display_date_time(d->dt_date_time); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_from --> + <sect2 id="mailimf-from"> + <title>mailimf_from - parsed content of From header</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_from { + struct mailimf_mailbox_list * frm_mb_list; /* != NULL */ +}; + +struct mailimf_from * +mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list); + +void mailimf_from_free(struct mailimf_from * from); + </programlisting> + + <para> + This is the content of a header <command>From</command> or + <command>Resent-From</command>. + </para> + <para> + <command>frm_mb_list</command> is the parsed mailbox list + (see <xref linkend="mailimf-mailbox-list">). + </para> + + <para> + <command>mailimf_from_new()</command> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_from_free()</command> frees memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>creation and display of a From header</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + /* do the things */ + mailimf_from_free(from); + + return 0; +} + +/* display content of from header */ + +#include <libetpan/libetpan.h> + +void display_from(struct mailimf_from * from) +{ + display_mailbox_list(from->frm_mb_list); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_sender --> + <sect2 id="mailimf-sender"> + <title>mailimf_sender - parsed content of Sender header</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_sender { + struct mailimf_mailbox * snd_mb; /* != NULL */ +}; + +struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb); + +void mailimf_sender_free(struct mailimf_sender * sender); + </programlisting> + + <para> + This is the content of a header <command>Sender</command> or + <command>Resent-Sender</command>. + </para> + + <para> + <command>snd_mb</command> is the parsed mailbox + (see <xref linkend="mailimf-mailbox">). + </para> + + <para> + <command>mailimf_sender_new()</command> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_sender_free()</command> This function frees + memory used by the structure and substructures + will also be released. + </para> + + <example> + <title>creation and display of Sender field</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + + sender = mailimf_sender_new(mb); + /* do the things */ + mailimf_sender_free(sender); + + return 0; +} + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_sender(struct mailimf_sender * sender) +{ + display_mailbox(sender->snd_mb); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_reply_to --> + <sect2 id="mailimf-reply-to"> + <title>mailimf_reply_to - parsed content of Reply-To header</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_reply_to { + struct mailimf_address_list * rt_addr_list; /* != NULL */ +}; + +struct mailimf_reply_to * +mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list); + +void mailimf_reply_to_free(struct mailimf_reply_to * reply_to); + </programlisting> + + <para> + This is the content of a header <command>Reply-To</command>. + </para> + + <para> + <command>addr_list</command> is the parsed address list + (see <xref linkend="mailimf-address-list">). + </para> + + <para> + <command>mailimf_reply_to_new()</command> creates and + initializes a data structure with a value. Structures given + as argument are referenced by the created object and will be + freed if the object is released. + </para> + + <para> + <command>mailimf_reply_to_free()</command> frees memory used + by the structure and substructures will also be released. + </para> + + <example> + <title>creation and display of Reply-To field</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_reply_to * reply_to; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + reply_to = mailimf_reply_to_new(addr_list); + /* do the things */ + mailimf_reply_to_free(reply_to); + + return 0; +} + +/* display Reply-To header */ + +#include <libetpan/libetpan.h> + +void display_reply_to(struct mailimf_reply_to * reply_to) +{ + display_address_list(reply_to->addr_list); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_to --> + <sect2 id="mailimf-to"> + <title>mailimf_to - parsed content of To header</title> + + <programlisting role="C"> + struct mailimf_to { + struct mailimf_address_list * to_addr_list; /* != NULL */ +}; + +struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list); + +void mailimf_to_free(struct mailimf_to * to); + </programlisting> + + <para> + This is the content of a header <command>To</command> or + <command>Resent-To</command>. + </para> + + <para> + <command>to_addr_list</command> is the parsed address list + (see <xref linkend="mailimf-address-list">). + </para> + + <para> + <command>mailimf_to_new()</command> creates and initializes a + data structure with a value. Structures given as argument + are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_to_free()</command> frees memory used by the + structure and substructures will also be released. + </para> + + <example> + <title>creation and display of To field</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + /* do the things */ + mailimf_to_free(to); + + return 0; +} + +/* display To header */ + +#include <libetpan/libetpan.h> + +void display_to(struct mailimf_to * to) +{ + display_address_list(to->to_addr_list); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_cc --> + <sect2 id="mailimf-cc"> + <title>mailimf_cc - parsed content of Cc</title> + +<programlisting> +#include <libetpan/libetpan.h> + +struct mailimf_cc { + struct mailimf_address_list * cc_addr_list; /* != NULL */ +}; + +struct mailimf_cc * +mailimf_cc_new(struct mailimf_address_list * cc_addr_list); + +void mailimf_cc_free(struct mailimf_cc * cc); +</programlisting> + + <para> + This is the content of a header <command>Cc</command> or + <command>Resent-Cc</command>. + </para> + + <para> + <command>cc_addr_list</command> is the parsed address list + (see <xref linkend="mailimf-address-list">). + </para> + + <para> + <command>mailimf_cc_new()</command> creates and initializes a + data structure with a value. Structures given as argument + are referenced by the created object and will be freed if + the object is released. + </para> + + <para> + <command>mailimf_cc_free()</command> This function frees + memory used by the structure and substructures will also be + released. + </para> + + <example> + <title>creation and display of Cc field</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + cc = mailimf_cc_new(addr_list); + /* do the things */ + mailimf_cc_free(cc); + + return 0; +} + +/* display content of Cc field */ + +#include <libetpan/libetpan.h> + +void display_cc(struct mailimf_cc * cc) +{ + display_address_list(cc->cc_addr_list); +} + + </programlisting> + </example> + + </sect2> + + <!-- mailimf_bcc --> + <sect2 id="mailimf-bcc"> + <title>mailimf_bcc - parsed content of Bcc field</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_bcc { + struct mailimf_address_list * bcc_addr_list; /* can be NULL */ +}; + +struct mailimf_bcc * +mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list); + +void mailimf_bcc_free(struct mailimf_bcc * bcc); + </programlisting> + + <para> + This is the content of a header <command>Bcc</command> or + <command>Resent-Bcc</command>. + </para> + + <para> + <command>bcc_addr_list</command> is the parsed address list + (see <xref linkend="mailimf-address-list">). + </para> + + <para> + <command>mailimf_bcc_new()</command> creates and initializes a + data structure with a value. Structures given as argument + are referenced by the created object and will be freed if + the object is released. + </para> + + <para> + <command>mailimf_bcc_free()</command> frees memory used by the + structure and substructures will also be released. + </para> + + <example> + <title>creation and display of Bcc field</title> + <programlisting role="C"> +/* create visible Bcc */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + bcc = mailimf_bcc_new(addr_list); + /* do the things */ + mailimf_bcc_free(bcc); + + return 0; +} + +/* create unvisible Bcc */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_bcc * bcc; + + bcc = mailimf_bcc_new(NULL); + /* do the things */ + mailimf_bcc_free(bcc); + + return 0; +} + +/* display content of Bcc field */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_bcc(struct mailimf_bcc * bcc) +{ + if (bcc->addr_list == NULL) { + printf("hidden Bcc\n"); + } + else { + display_address_list(bcc->bcc_addr_list); + } +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_message_id --> + <sect2 id="mailimf-message-id"> + <title>mailimf_message_id - parsed content of Message-ID header</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_message_id { + char * mid_value; /* != NULL */ +}; + +struct mailimf_message_id * mailimf_message_id_new(char * mid_value); + +void mailimf_message_id_free(struct mailimf_message_id * message_id); + </programlisting> + + <para> + This is the content of a header <command>Message-ID</command> + or <command>Resent-Message-ID</command>. For example : + </para> + + <example> + <title>example of Message-ID</title> + <programlisting> +Message-ID: <200312100009.43592@c01n-c01n.plop.P4N>> + </programlisting> + </example> + + <para> + <command>mid_value</command> is the message identifier. + It is not enclosed by angle bracket. + </para> + + <para> + <command>mailimf_message_id_new()</command> This function + creates and initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + The given string is allocated with + <command>malloc()</command> and is not enclosed by angle bracket. + </para> + + <para> + <command>mailimf_message_id_free()</command> frees memory + used by the structure and substructures will also be + released. + </para> + + <example> + <title>creation and display of Message-ID field</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_message_id * msg_id; + char * id; + + id = strdup("1037197913.3dd26259752fa@imp.free.fr"); + msg_id = mailimf_message_id_new(id); + /* do the things */ + mailimf_message_id_free(msg_id); + + return 0; +} + +/* display message id */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_message_id(struct mailimf_message_id * msg_id) +{ + printf("%s\n", msg_id->mid_value); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_in_reply_to --> + <sect2 id="mailimf-in-reply-to"> + <title>mailimf_in_reply_to - parsed content of In-Reply-To + field</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_in_reply_to { + clist * mid_list; /* list of (char *), != NULL */ +}; + +struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list); + +void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to); + </programlisting> + + <para> + content of a header <command>In-Reply-To</command>. + For example : + </para> + + <programlisting> +In-Reply-To: <etPan.3fd5fa29.4c3901c1.6b39@homer> + </programlisting> + + <para> + <command>mid_list</command> is a <command>clist</command> + in which elements are message identifiers. + their types are <command>(char *)</command> and they are + allocated with <command>malloc()</command>. + </para> + + <para> + <command>mailimf_in_reply_to_new()</command> creates and + initializes a data structure with a value. Structures given + as argument are referenced by the created object and will be + freed if the object is released. + </para> + + <para> + <command>mailimf_in_reply_to_free()</command> frees memory + used by the structure and substructures will also be + released. + </para> + + <example> + <title>creation and display of In-Reply-To field</title> + <programlisting> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_in_reply_to * in_reply_to; + clist * msg_id_list; + + msg_id_list = clist_new(); + clist_append(msg_id_list, + strdup("etPan.3ebbcc18.4014197f.bc1@homer.invalid")); + + in_reply_to = mailimf_in_reply_to_new(msg_id_list); + /* do the things */ + mailimf_in_reply_to_free(in_reply_to); + + return 0; +} + +/* display the content of mailimf_in_reply_to */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_in_reply_to(struct mailimf_in_reply_to * in_reply_to) +{ + clistiter * cur; + + for(cur = clist_begin(in_reply_to->mid_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * str; + + str = clist_content(cur); + + printf("%s\n", str); + } +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_references --> + <sect2 id="mailimf-references"> + <title>mailimf_references - parsed content of References field</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_references { + clist * mid_list; /* list of (char *) */ + /* != NULL */ +}; + +struct mailimf_references * mailimf_references_new(clist * mid_list); + +void mailimf_references_free(struct mailimf_references * references); + </programlisting> + + <para> + This is the content of a header <command>References</command>. + For example : + </para> + <programlisting> +In-Reply-To: <etPan.3fd5fa29.4c3901c1.6b39@homer> + <3FD5FA78.A1D98E7@oleane.net> + <etPan.3fd5fc69.2b349482.730e@homer> + </programlisting> + + <para> + <command>mid_list</command> is a <command>clist</command> + in which elements are message identifiers. + their types are <command>(char *)</command> and they are + allocated with <command>malloc()</command>. + </para> + + <para> + <command>mailimf_references_new()</command> creates and + initializes a data structure with a value. Structures given + as argument are referenced by the created object and will be + freed if the object is released. + </para> + + <para> + <command>mailimf_references_free()</command> frees memory + used by the structure and substructures will also be + released. + </para> + + <example> + <title>creation and display of References field</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_references * ref; + clist * msg_id_list; + + msg_id_list = clist_new(); + clist_append(msg_id_list, + strdup("200304280144.23633.wim.delvaux@adaptiveplanet.com")); + clist_append(msg_id_list, + strdup("200304301153.19688.wim.delvaux@adaptiveplanet.com")); + clist_append(msg_id_list, + strdup("etPan.3eb29de4.5fc4d652.3f83@homer")); + + ref = mailimf_references_new(msg_id_list); + /* do the things */ + mailimf_in_reply_to_free(ref); + + return 0; +} + +/* display references */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_references(struct mailimf_references * ref) +{ + clistiter * cur; + + for(cur = clist_begin(ref->mid_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * msg_id; + + msg_id = clist_content(cur); + + printf("%s\n", msg_id); + } +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_subject --> + <sect2 id="mailimf-subject"> + <title>mailimf_subject - parsed content of Subject field</title> + +<programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_subject { + char * sbj_value; /* != NULL */ +}; + +struct mailimf_subject * mailimf_subject_new(char * sbj_value); + +void mailimf_subject_free(struct mailimf_subject * subject); +</programlisting> + + <para> + This is the content of a header <command>Subject</command>. + </para> + + <para> + <command>sbj_value</command> is the value of the field. + </para> + + <para> + <command>mailimf_subject_new()</command> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_subject_free</command> frees memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>creation and display of Subject field</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_subject * subject; + + subject = mailimf_subject_new(strdup("example of subject")); + /* do the things */ + mailimf_subject_free(subject); + + return 0; +} + +/* display subject header */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_subject(struct mailimf_subject * subject) +{ + printf("%s\n", subject->value); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_comments --> + <sect2 id="mailimf-comments"> + <title>mailimf_comments - parsed content of Comments field</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_comments { + char * cm_value; /* != NULL */ +}; + +struct mailimf_comments * mailimf_comments_new(char * cm_value); + +void mailimf_comments_free(struct mailimf_comments * comments); + </programlisting> + + <para> + This is the content of a header <command>Comments</command>. + </para> + + <para> + <command>cm_value</command> is the value of the field. + </para> + + <para> + <command>mailimf_comments_new()</command> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_comments_free()</command> frees memory used + by the structure and substructures will also be released. + </para> + + <example> + <title>creation and display of Comment field</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_comments * comments; + + comments = mailimf_comments_new(strdup("example of comment")); + /* do the things */ + mailimf_comments_free(comments); + + return 0; +} + +/* display the content of a comments */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_comments(struct mailimf_comments * comments) +{ + printf("%s\n", comments->cm_value); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_keywords --> + <sect2 id="mailimf-keywords"> + <title>mailimf_keywords - parsed content of Keywords field</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_keywords { + clist * kw_list; /* list of (char *), != NULL */ +}; + +struct mailimf_keywords * mailimf_keywords_new(clist * kw_list); + +void mailimf_keywords_free(struct mailimf_keywords * keywords); + </programlisting> + + <para> + This is the content of a header <command>Keywords</command>. + </para> + + <para> + <command>kw_list</command> is the list of keywords. This is + a list of <command>(char *)</command> allocated with malloc(). + </para> + + <para> + <command>mailimf_keywords_new()</command> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_keywords_free()</command> frees memory used + by the structure and substructures will also be released. + </para> + + <example> + <title>creation and display of Keywords field</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_keywords * keywords; + clist * list; + + list = clist_new(); + clist_append(list, strdup("sauerkraut")); + clist_append(list, strdup("potatoes")); + clist_append(list, strdup("cooking")); + + keywords = mailimf_keywords_new(list); + /* do the things */ + mailimf_keywords_free(keywords); + + return 0; +} + +/* display the content of mailimf_in_reply_to */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_keywords(struct mailimf_keywords * kw) +{ + clistiter * cur; + + for(cur = clist_begin(kw->kw_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * str; + + str = clist_content(cur); + + printf("%s\n", str); + } +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_return --> + <sect2 id="mailimf-return"> + <title>mailimf_return - parsed content of Return-Path field</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_return { + struct mailimf_path * ret_path; /* != NULL */ +}; + +struct mailimf_return * +mailimf_return_new(struct mailimf_path * ret_path); + +void mailimf_return_free(struct mailimf_return * return_path); + </programlisting> + + <para> + This is the content of a header + <command>Return-Path</command>. + </para> + + <para> + <command>ret_path</command> is the parsed value of Return-Path + (see <xref linkend="mailimf-path">). + </para> + + <para> + <command>mailimf_return_new()</command> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_return_free()</command> frees memory used + by the structure and substructures will also be released. + </para> + + <example> + <title>creation and display of Return-Path field</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_path * path; + struct mailimf_return * r; + + path = mailimf_path_new(strdup("dinh.viet.hoa@free.fr")); + r = mailimf_return_new(path); + /* do the things */ + mailimf_return_free(r); + + return 0; +} + +/* display return path */ + +#include <libetpan/libetpan.h> + +void display_return(struct mailimf_return * r) +{ + display_path(r->ret_path); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_path --> + <sect2 id="mailimf-path"> + <title>mailimf_path - address in Return-Path field</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_path { + char * pt_addr_spec; /* can be NULL */ +}; + +struct mailimf_path * mailimf_path_new(char * pt_addr_spec); + +void mailimf_path_free(struct mailimf_path * path); + </programlisting> + + <para> + This is the encapsulation of address specifier for + <command>Return-Path</command> content. + </para> + + <para> + <command>pt_addr_spec</command> is a mailbox destination. + </para> + + <para> + <command>mailimf_path_new()</command> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + The given string is allocated with + <command>malloc()</command>. This is a address + specifier. + </para> + + <para> + <command>mailimf_path_free()</command> frees memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>Creation and display of return path</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_path * path; + + path = mailimf_path_new(strdup("dinh.viet.hoa@free.fr")); + /* do the things */ + mailimf_path_free(r); + + return 0; +} + +/* display return path */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_path(struct mailimf_path * path) +{ + printf("%s\n", path->pt_addr_spec); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_optional_field --> + <sect2 id="mailimf-optional-field"> + <title>mailimf_optional_field - non-standard header</title> + + <programlisting> +#include <libetpan/libetpan.h> + +struct mailimf_optional_field { + char * fld_name; /* != NULL */ + char * fld_value; /* != NULL */ +}; + +struct mailimf_optional_field * +mailimf_optional_field_new(char * fld_name, char * fld_value); + +void mailimf_optional_field_free(struct mailimf_optional_field * opt_field); + </programlisting> + + <para> + This is a non-standard header or unparsed header. + </para> + + <itemizedlist> + <listitem> + <para> + <command>fld_name</command> is the name of the header + field. + </para> + </listitem> + <listitem> + <para> + <command>fld_value</command> is the value of the header + field. + </para> + </listitem> + </itemizedlist> + + <para> + <command>mailimf_optional_field_new()</command> This + function creates and initializes a data structure with a + value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + </para> + + <para> + field name and field value have to be allocated with + <command>malloc()</command>. + </para> + + <para> + <command>mailimf_optional_field_free()</command> This + function frees memory used by the structure and + substructures will also be released. + </para> + + <example> + <title>creation and display of non-standard fields</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_optional_field * opt; + + opt = mailimf_optional_field_new(strdup("X-My-Field"), strdup("my value")); + /* do the things */ + mailimf_optional_field_free(opt); + + return 0; +} + +/* display the optional field */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_optional_field(struct mailimf_optional_field * opt) +{ + printf("%s: %s\n", opt->fld_name, opt->fld_value); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_field --> + <sect2 id="mailimf-field"> + <title>mailimf_field - header field</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +enum { + MAILIMF_FIELD_NONE, /* on parse error */ + MAILIMF_FIELD_RETURN_PATH, /* Return-Path */ + MAILIMF_FIELD_RESENT_DATE, /* Resent-Date */ + MAILIMF_FIELD_RESENT_FROM, /* Resent-From */ + MAILIMF_FIELD_RESENT_SENDER, /* Resent-Sender */ + MAILIMF_FIELD_RESENT_TO, /* Resent-To */ + MAILIMF_FIELD_RESENT_CC, /* Resent-Cc */ + MAILIMF_FIELD_RESENT_BCC, /* Resent-Bcc */ + MAILIMF_FIELD_RESENT_MSG_ID, /* Resent-Message-ID */ + MAILIMF_FIELD_ORIG_DATE, /* Date */ + MAILIMF_FIELD_FROM, /* From */ + MAILIMF_FIELD_SENDER, /* Sender */ + MAILIMF_FIELD_REPLY_TO, /* Reply-To */ + MAILIMF_FIELD_TO, /* To */ + MAILIMF_FIELD_CC, /* Cc */ + MAILIMF_FIELD_BCC, /* Bcc */ + MAILIMF_FIELD_MESSAGE_ID, /* Message-ID */ + MAILIMF_FIELD_IN_REPLY_TO, /* In-Reply-To */ + MAILIMF_FIELD_REFERENCES, /* References */ + MAILIMF_FIELD_SUBJECT, /* Subject */ + MAILIMF_FIELD_COMMENTS, /* Comments */ + MAILIMF_FIELD_KEYWORDS, /* Keywords */ + MAILIMF_FIELD_OPTIONAL_FIELD, /* other field */ +}; + +struct mailimf_field { + int fld_type; + union { + struct mailimf_return * fld_return_path; /* can be NULL */ + struct mailimf_orig_date * fld_resent_date; /* can be NULL */ + struct mailimf_from * fld_resent_from; /* can be NULL */ + struct mailimf_sender * fld_resent_sender; /* can be NULL */ + struct mailimf_to * fld_resent_to; /* can be NULL */ + struct mailimf_cc * fld_resent_cc; /* can be NULL */ + struct mailimf_bcc * fld_resent_bcc; /* can be NULL */ + struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */ + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ + struct mailimf_optional_field * fld_optional_field; /* can be NULL */ + } fld_data; +}; + +struct mailimf_field * +mailimf_field_new(int fld_type, + struct mailimf_return * fld_return_path, + struct mailimf_orig_date * fld_resent_date, + struct mailimf_from * fld_resent_from, + struct mailimf_sender * fld_resent_sender, + struct mailimf_to * fld_resent_to, + struct mailimf_cc * fld_resent_cc, + struct mailimf_bcc * fld_resent_bcc, + struct mailimf_message_id * fld_resent_msg_id, + struct mailimf_orig_date * fld_orig_date, + struct mailimf_from * fld_from, + struct mailimf_sender * fld_sender, + struct mailimf_reply_to * fld_reply_to, + struct mailimf_to * fld_to, + struct mailimf_cc * fld_cc, + struct mailimf_bcc * fld_bcc, + struct mailimf_message_id * fld_message_id, + struct mailimf_in_reply_to * fld_in_reply_to, + struct mailimf_references * fld_references, + struct mailimf_subject * fld_subject, + struct mailimf_comments * fld_comments, + struct mailimf_keywords * fld_keywords, + struct mailimf_optional_field * fld_optional_field); + +void mailimf_field_free(struct mailimf_field * field); + </programlisting> + + <para> + This is one header field of a message. + </para> + + <itemizedlist> + <listitem> + <para> + <command>type</command> is the type of the field. This define the + type of the field. + Only the corresponding field should be, then, + filled. The value of this field can be one of : + <command>MAILIMF_FIELD_RETURN_PATH</command>, + <command>MAILIMF_FIELD_RESENT_DATE</command>, + <command>MAILIMF_FIELD_RESENT_FROM</command>, + <command>MAILIMF_FIELD_RESENT_SENDER</command>, + <command>MAILIMF_FIELD_RESENT_TO</command>, + <command>MAILIMF_FIELD_RESENT_CC</command>, + <command>MAILIMF_FIELD_RESENT_BCC</command>, + <command>MAILIMF_FIELD_RESENT_MSG_ID</command>, + <command>MAILIMF_FIELD_ORIG_DATE</command>, + <command>MAILIMF_FIELD_FROM</command>, + <command>MAILIMF_FIELD_SENDER</command>, + <command>MAILIMF_FIELD_REPLY_TO</command>, + <command>MAILIMF_FIELD_TO</command>, + <command>MAILIMF_FIELD_CC</command>, + <command>MAILIMF_FIELD_BCC</command>, + <command>MAILIMF_FIELD_MESSAGE_ID</command>, + <command>MAILIMF_FIELD_IN_REPLY_TO</command>, + <command>MAILIMF_FIELD_REFERENCES</command>, + <command>MAILIMF_FIELD_SUBJECT</command>, + <command>MAILIMF_FIELD_COMMENTS</command>, + <command>MAILIMF_FIELD_KEYWORDS</command>, + <command>MAILIMF_FIELD_OPTIONAL_FIELD</command>. + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_return_path</command> is the + parsed content of the Return-Path field + if type is <command>MAILIMF_FIELD_RETURN_PATH</command> + (see <xref linkend="mailimf-return">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_resent_date</command> is the + parsed content of the Resent-Date field + if type is <command>MAILIMF_FIELD_RESENT_DATE</command> + (see <xref linkend="mailimf-orig-date">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_resent_from</command> is the + parsed content of the Resent-From field + if type is <command>MAILIMF_FIELD_RESENT_FROM</command> + (see <xref linkend="mailimf-from">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_resent_sender</command> is the + parsed content of the Resent-Sender field + if type is <command>MAILIMF_FIELD_RESENT_SENDER</command> + (see <xref linkend="mailimf-sender">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_resent_to</command> is the parsed + content of the Resent-To field + if type is <command>MAILIMF_FIELD_RESENT_TO</command> + (see <xref linkend="mailimf-to">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_resent_cc</command> is the parsed + content of the Resent-Cc field + if type is <command>MAILIMF_FIELD_CC</command> + (see <xref linkend="mailimf-cc">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_resent_bcc</command> is the parsed + content of the Resent-Bcc field + if type is <command>MAILIMF_FIELD_BCC</command> + (see <xref linkend="mailimf-bcc">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_resent_msg_id</command> is the + parsed content of the Resent-Message-ID field + if type is <command>MAILIMF_FIELD_RESENT_MSG_ID</command> + (see <xref linkend="mailimf-message-id">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_orig_date</command> is the parsed + content of the Date field + if type is <command>MAILIMF_FIELD_ORIG_DATE</command> + (see <xref linkend="mailimf-orig-date">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_from</command> is the parsed + content of the From field + if type is <command>MAILIMF_FIELD_FROM</command> + (see <xref linkend="mailimf-from">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_sender</command> is the parsed + content of the Sender field + if type is <command>MAILIMF_FIELD_SENDER</command> + (see <xref linkend="mailimf-sender">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_reply_to</command> is the parsed + content of the Reply-To field + if type is <command>MAILIMF_FIELD_REPLY_TO</command> + (see <xref linkend="mailimf-reply-to">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_to</command> is the parsed content + of the To field if type is + <command>MAILIMF_FIELD_TO</command> + (see <xref linkend="mailimf-to">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_cc</command> is the parsed content + of the Cc field if type is + <command>MAILIMF_FIELD_CC</command> + (see <xref linkend="mailimf-cc">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_bcc</command> is the parsed + content of the Bcc field if type is + <command>MAILIMF_FIELD_BCC</command> + (see <xref linkend="mailimf-bcc">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_message_id</command> is the parsed + content of the Message-ID field + if type is <command>MAILIMF_FIELD_MESSAGE_ID</command> + (see <xref linkend="mailimf-message-id">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_in_reply_to</command> is the + parsed content of the In-Reply-To field + if type is <command>MAILIMF_FIELD_IN_REPLY_TO</command> + (see <xref linkend="mailimf-in-reply-to">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_references</command> is the parsed + content of the References field + if type is <command>MAILIMF_FIELD_REFERENCES</command> + (see <xref linkend="mailimf-references">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_subject</command> is the content + of the Subject field + if type is <command>MAILIMF_FIELD_SUBJECT</command> + (see <xref linkend="mailimf-subject">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_comments</command> is the content of the + Comments field + if type is <command>MAILIMF_FIELD_COMMENTS</command> + (see <xref linkend="mailimf-comments">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_keywords</command> is the parsed + content of the Keywords field + if type is <command>MAILIMF_FIELD_KEYWORDS</command> + (see <xref linkend="mailimf-keywords">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_optional_field</command> is an + other field and is not parsed + if type is <command>MAILIMF_FIELD_OPTIONAL_FIELD</command> + (see <xref linkend="mailimf-optional-field">). + </para> + </listitem> + </itemizedlist> + + <para> + <command>mailimf_field_new()</command> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_field_free()</command> frees memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>creation and display of field</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_field * f; + struct mailimf_mailbox * mb; + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + /* do the things */ + mailimf_field_free(f); + + return 0; +} + +/* display content of the header */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_field(struct mailimf_field * field) +{ + switch (field->type) { + case MAILIMF_FIELD_RETURN_PATH: + printf("Return-Path:\n"); + display_return(field->fld_data.fld_return_path); + break; + case MAILIMF_FIELD_RESENT_DATE: + printf("Resent-Date:\n"); + display_orig_date(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_RESENT_FROM: + printf("Resent-From:\n"); + display_from(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_RESENT_SENDER: + printf("Resent-Sender:\n"); + display_sender(field->fld_data.fld_resent_sender); + break; + case MAILIMF_FIELD_RESENT_TO: + printf("Resent-To:\n"); + display_to(field->fld_data.fld_resent_to); + break; + case MAILIMF_FIELD_RESENT_CC: + printf("Resent-Cc:\n"); + display_from(field->fld_data.fld_resent_cc); + break; + case MAILIMF_FIELD_RESENT_BCC: + printf("Resent-Bcc:\n"); + display_from(field->fld_data.fld_resent_bcc); + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + printf("Resent-Message-ID:\n"); + display_message_id(field->fld_data.fld_resent_msg_id); + break; + case MAILIMF_FIELD_ORIG_DATE: + printf("Date:\n"); + display_orig_date(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + printf("From:\n"); + display_from(field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + printf("Sender:\n"); + display_sender(field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + printf("Reply-To:\n"); + display_reply_to(field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + printf("To:\n"); + display_to(field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + printf("Cc:\n"); + display_cc(field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + printf("Bcc:\n"); + display_bcc(field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + printf("Message-ID:\n"); + display_message_id(field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + printf("In-Reply-To:\n"); + display_in_reply_to(field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + printf("References:\n"); + display_references(field->fld_data.fld_references_to); + break; + case MAILIMF_FIELD_SUBJECT: + printf("Subject:\n"); + display_subject(field->fld_data.fld_subject); + break; + case MAILIMF_FIELD_COMMENTS: + printf("Comments:\n"); + display_comments(field->fld_data.fld_comments); + break; + case MAILIMF_FIELD_KEYWORDS: + printf("Keywords:\n"); + display_keywords(field->fld_data.fld_keywords); + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + printf("[optional field]:\n"); + display_optional_field(field->fld_data.fld_optional_field); + break; + } +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_fields --> + <sect2 id="mailimf-fields"> + <title>mailimf_fields - list of header fields</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_fields { + clist * fld_list; /* list of (struct mailimf_field *), != NULL */ +}; + +struct mailimf_fields * mailimf_fields_new(clist * fld_list); + +void mailimf_fields_free(struct mailimf_fields * fields); + </programlisting> + + <para> + This is the list of header fields of a message. + </para> + + <para> + <command>fld_list</command> is a list of header fields. This + is a <command>clist</command> which elements are + of type <command>mailimf_field</command> (see <xref + linkend="mailimf-field">). + </para> + + <para> + <command>mailimf_fields_new()</command> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_fields_free()</command> frees memory used + by the structure and substructures will also be released. + </para> + + <example> + <title>creation and display of header fields</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_field * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + /* do the things */ + mailimf_fields_free(fields); + + return 0; +} + +/* display list of headers */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_fields(struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(field->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_field * f; + + f = clist_content(cur); + + display_field(f); + printf("\n"); + } +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_body --> + <sect2 id="mailimf-body"> + <title>mailimf_body - message body without headers</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_body { + const char * bd_text; /* != NULL */ + size_t bd_size; +}; + +struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size); + +void mailimf_body_free(struct mailimf_body * body); + </programlisting> + + <para> + This is the text content of a message (without headers). + </para> + <para> + <itemizedlist> + <listitem> + <para> + <command>bd_text</command> is the beginning of the + text part, it is a substring of an other string. + It is not necessarily zero terminated. + </para> + </listitem> + <listitem> + <para> + <command>bd_size</command> is the size of the text part + </para> + </listitem> + </itemizedlist> + </para> + + <para> + <command>mailimf_body_new()</command> creates and + initializes a data structure with a value. + Text given as argument will <emphasis>NOT</emphasis> be released. + </para> + + <para> + <command>mailimf_body_free()</command> frees memory used by + the structure. + </para> + + <example> + <title>creation and display of message body</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_body * b; + + b = mailimf_body_new("this is the content of the message", 34); + /* do the things */ + mailimf_body_free(b); + + return 0; +} + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_body(struct mailimf_body * b) +{ + char * text; + + text = malloc(b->size + 1); + strncpy(text, b->bd_text, b->bd_size); + text[b->size] = 0; + + puts(text); + printf("\n"); + + free(text); + + return 0; +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_message --> + <sect2 id="mailimf-message"> + <title>mailimf_message - parsed message</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_message { + struct mailimf_fields * msg_fields; /* != NULL */ + struct mailimf_body * msg_body; /* != NULL */ +}; + +struct mailimf_message * +mailimf_message_new(struct mailimf_fields * msg_fields, + struct mailimf_body * msg_body); + +void mailimf_message_free(struct mailimf_message * message); + </programlisting> + + <para> + This is the message content (text and headers). + </para> + + <itemizedlist> + <listitem> + <para> + <command>msg_fields</command> is the header fields of + the message + (see <xref linkend="mailimf-fields">). + </para> + </listitem> + <listitem> + <para> + <command>msg_body</command> is the text part of the message + (see <xref linkend="mailimf-body">). + </para> + </listitem> + </itemizedlist> + + <para> + <command>mailimf_message_new()</command> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailimf_message_free()</command> frees memory used + by the structure and substructures will also be released. + </para> + + <example> + <title>creation and display of message</title> + <programlisting> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_body * b; + struct mailimf_message * m; + struct mailimf_fields * fields; + struct mailimf_fields * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build text content */ + + b = mailimf_body_new("this is the content of the message", 34); + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + + /* build message */ + + m = mailimf_message_new(fields, b); + /* do the things */ + mailimf_message_free(m); + + return 0; +} + +/* display the message */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_message(struct mailimf_message * msg) +{ + display_fields(msg->msg_fields); + printf("\n"); + display_body(msg->msg_body); + printf("\n"); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_single_fields --> + <sect2 id="mailimf-single-fields"> + <title>mailimf_single_fields - simplified fields</title> + +<programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_single_fields { + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ +}; + +struct mailimf_single_fields * +mailimf_single_fields_new(struct mailimf_fields * fields); + +void mailimf_single_fields_free(struct mailimf_single_fields * + single_fields); + +void mailimf_single_fields_init(struct mailimf_single_fields * single_fields, + struct mailimf_fields * fields); +</programlisting> + + <para> + Structure that contains some standard fields and allows access + to a given header without running through the list. + </para> + + <para> + mailimf_fields is the native structure that IMF module will use, + this module will provide an easier structure to use when + parsing fields. + mailimf_single_fields is an easier structure to get parsed fields, + rather than iteration over the list of fields + </para> + + <itemizedlist> + <listitem> + <para> + <command>fld_orig_date</command> is the parsed "Date" + field + (see <xref linkend="mailimf-orig-date">). + </para> + </listitem> + <listitem> + <para> + <command>fld_from</command> is the parsed "From" field + (see <xref linkend="mailimf-from">). + </para> + </listitem> + <listitem> + <para> + <command>fld_sender</command> is the parsed "Sender "field + (see <xref linkend="mailimf-sender">). + </para> + </listitem> + <listitem> + <para> + <command>reply_to</command> is the parsed "Reply-To" field + (see <xref linkend="mailimf-reply-to">). + </para> + </listitem> + <listitem> + <para> + <command>fld_to</command> is the parsed "To" field + (see <xref linkend="mailimf-to">). + </para> + </listitem> + <listitem> + <para> + <command>fld_cc</command> is the parsed "Cc" field + (see <xref linkend="mailimf-cc">). + </para> + </listitem> + <listitem> + <para> + <command>fld_bcc</command> is the parsed "Bcc" field + (see <xref linkend="mailimf-bcc">). + </para> + </listitem> + <listitem> + <para> + <command>fld_message_id</command> is the parsed + "Message-ID" field. + (see <xref linkend="mailimf-message-id">). + </para> + </listitem> + <listitem> + <para> + <command>fld_in_reply_to</command> is the parsed + "In-Reply-To" field. + (see <xref linkend="mailimf-in-reply-to">). + </para> + </listitem> + <listitem> + <para> + <command>fld_references</command> is the parsed + "References" field. + (see <xref linkend="mailimf-references">). + </para> + </listitem> + <listitem> + <para> + <command>fld_subject</command> is the parsed "Subject" field + (see <xref linkend="mailimf-subject">). + </para> + </listitem> + <listitem> + <para> + <command>fld_comments</command> is the parsed "Comments" field + (see <xref linkend="mailimf-comments">). + </para> + </listitem> + <listitem> + <para> + <command>fld_keywords</command> is the parsed "Keywords" field + (see <xref linkend="mailimf-keywords">). + </para> + </listitem> + </itemizedlist> + + <para> + <command>mailimf_single_fields_new()</command> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will <emphasis>NOT</emphasis> be freed if the + object is released. + </para> + + <para> + <command>mailimf_single_fields_free()</command> frees memory + used by the structure and + substructures will <emphasis>NOT</emphasis> be + released. They should be released by the application. + </para> + + <para> + <command>mailimf_single_fields_init()</command> will + initialize fill the data structure, using + the given argument (<command>fields</command>). The + interesting fields will be filled into + <command>single_fields</command>. + </para> + + <example> + <title>using mailimf_single_fields</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_single_fields * single_fields; + struct mailimf_fields * fields; + struct mailimf_field * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + + /* create the single fields */ + single_fields = mailimf_single_fields_new(fields); + /* do the things */ + mailimf_single_fields_free(single_fields); + mailimf_fields_free(fields); + + return 0; +} + </programlisting> + </example> + + <example> + <title>using mailimf_single_fields without memory allocation</title> + <programlisting> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_single_fields single_fields; + struct mailimf_fields * fields; + struct mailimf_field * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + + /* fill the single fields */ + mailimf_fields_fields_init(&single_fields, fields); + /* do the things */ + mailimf_fields_free(fields); + + return 0; +} + </programlisting> + </example> + </sect2> + </sect1> + + <!-- parser functions --> + <sect1> + <title>Parser functions</title> + + <!-- mailimf_address_list_parse --> + <sect2 id="mailimf-address-list-parse"> + <title>mailimf_address_list_parse</title> + <programlisting role="C"> +int +mailimf_address_list_parse(char * message, size_t length, + size_t * index, + struct mailimf_address_list ** result); + </programlisting> + + <para> + <command>mailimf_address_list_parse()</command> parse a list + of addresses in RFC 2822 form. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> this is a string containing + the list of addresses. + </para> + </listitem> + <listitem> + <para> + <command>length</command> this is the size of the given string + </para> + </listitem> + <listitem> + <para> + <command>index</command> this is a pointer to the + start of the list of + addresses in the given string, + <command>(* index)</command> is modified to point + at the end of the parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command> the result of the parse + operation is stored in + <command>(* result)</command> + (see <xref linkend="mailimf-address-list">). + </para> + </listitem> + </itemizedlist> + + <para> + return <command>MAILIMF_NO_ERROR</command> on success, + <command>MAILIMF_ERROR_XXX</command> on error. + </para> + + <example> + <title>parsing a list of addresses</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_address_list * addr_list; + size_t current_index; + + current_index = 0; + r = mailimf_address_list_parse(mem, stat_info.st_size, + ¤t_index, &addr_list); + if (r == MAILIMF_NO_ERROR) { + display_address_list(addr_list); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_address_list_free(addr_list); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_address_parse --> + <sect2 id="mailimf-address-parse"> + <title>mailimf_address_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int +mailimf_address_parse(char * message, size_t length, + size_t * index, + struct mailimf_address ** result); + </programlisting> + + <para> + <command>mailimf_address_parse()</command> parse an address + in RFC 2822 form. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> this is a string containing the + address. + </para> + </listitem> + <listitem> + <para> + <command>length</command> this is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> index this is a pointer to the + start of the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command> the result of the parse operation + is stored in <command>(* result)</command> + (see <xref linkend="mailimf-address">). + </para> + </listitem> + </itemizedlist> + + <para> + return <command>MAILIMF_NO_ERROR</command> on success, + <command>MAILIMF_ERROR_XXX</command> on error. + </para> + + <example> + <title>parsing an address</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_address * addr; + size_t current_index; + + current_index = 0; + r = mailimf_address_parse(mem, stat_info.st_size, + ¤t_index, &addr); + if (r == MAILIMF_NO_ERROR) { + display_address(addr); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_address_free(addr); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + + </sect2> + + <!-- mailimf_body_parse --> + <sect2 id="mailimf-body-parse"> + <title>mailimf_body_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailimf_body_parse(char * message, size_t length, + size_t * index, + struct mailimf_body ** result); + </programlisting> + + <para> + <command>mailimf_body_parse()</command> parse text body of a + message. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> this is a string containing + the message body part. + </para> + </listitem> + <listitem> + <para> + <command>length</command> this is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> this is a pointer to the start + of the message text part in + the given string, <command>(* index)</command> is + modified to point at the end + of the parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command> the result of the parse + operation is stored in + <command>(* result)</command> + (see <xref linkend="mailimf-body">). + </para> + </listitem> + </itemizedlist> + + <para> + return <command>MAILIMF_NO_ERROR</command> on success, + <command>MAILIMF_ERROR_XXX</command> on error. + </para> + + <example> + <title>parsing a message body</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_body * b; + struct mailimf_fields * f; + size_t current_index; + size_t size; + + size = stat_info.st_size; + current_index = 0; + r = mailimf_fields_parse(mem, size, ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + r = mailimf_crlf_parse(mem, size, ¤t_index); + /* ignore parse error of crlf */ + + r = mailimf_body_parse(mem, size, ¤t_index, &b); + if (r == MAILIMF_NO_ERROR) { + + display_body(b); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_body_free(b); + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + + </sect2> + + <!-- mailimf_envelope_and_optional_fields_parse --> + <sect2 id="mailimf-envelope-and-optional-fields-parse"> + <title>mailimf_envelope_and_optional_fields_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int +mailimf_envelope_and_optional_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + </programlisting> + + <para> + <command>mailimf_envelope_and_optional_fields_parse()</command> + returns a list of most useful headers (parsed). The other + headers will be placed in the list in a non-parsed form. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> this is a string containing the header. + </para> + </listitem> + <listitem> + <para> + <command>length</command> this is the size of the given string + </para> + </listitem> + <listitem> + <para> + <command>index</command> index this is a pointer to the + start of the header in the given string, <command>(* + index)</command> is modified to point at the end + of the parsed data + </para> + </listitem> + <listitem> + <para> + <command>result</command> the result of the parse + operation is stored in <command>(* result)</command> + (see <xref linkend="mailimf-fields">). + </para> + </listitem> + </itemizedlist> + + <para> + return <command>MAILIMF_NO_ERROR</command> on success, + <command>MAILIMF_ERROR_XXX</command> on error. + </para> + + <example> + <title>parsing commonly used fields and return other fields + in a non-parsed form</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_envelope_and_optional_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + + </sect2> + + <!-- mailimf_envelope_fields_parse --> + <sect2 id="mailimf-envelope-fields-parse"> + <title>mailimf_envelope_fields_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailimf_envelope_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + </programlisting> + + <para> + <command>mailimf_envelope_fields_parse()</command> return a + list of most useful headers (parsed). + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> this is a string containing the header + </para> + </listitem> + <listitem> + <para> + <command>length</command> this is the size of the given string + </para> + </listitem> + <listitem> + <para> + <command>index</command> index this is a pointer to the + start of the header in + the given string, <command>(* index)</command> is + modified to point at the end + of the parsed data + </para> + </listitem> + <listitem> + <para> + <command>result</command> the result of the parse + operation is stored in + <command>(* result)</command> + (see <xref linkend="mailimf-fields">). + </para> + </listitem> + </itemizedlist> + + <para> + return <command>MAILIMF_NO_ERROR</command> on success, + <command>MAILIMF_ERROR_XXX</command> on error. + </para> + + <example> + <title>parsing commonly used fields</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_envelope_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + + </sect2> + + <!-- mailimf_optional_fields_parse --> + <sect2 id="mailimf-optional-fields-parse"> + <title>mailimf_optional_fields_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int +mailimf_optional_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + </programlisting> + + <para> + <command>mailimf_optional_fields_parse</command> return a + list of non-parsed headers. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> this is a string containing the header + </para> + </listitem> + <listitem> + <para> + <command>length</command> this is the size of the given string + </para> + </listitem> + <listitem> + <para> + <command>index</command> index this is a pointer to the + start of the header in + the given string, <command>(* index)</command> is + modified to point at the end + of the parsed data + </para> + </listitem> + <listitem> + <para> + <command>result</command> the result of the parse + operation is stored in + <command>(* result)</command> + (see <xref linkend="mailimf-fields">). + </para> + </listitem> + </itemizedlist> + + <para> + return <command>MAILIMF_NO_ERROR</command> on success, + <command>MAILIMF_ERROR_XXX</command> on error. + </para> + + <example> + <title>parsing optional fields</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_optional_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_fields_parse --> + <sect2 id="mailimf-fields-parse"> + <title>mailimf_fields_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailimf_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + </programlisting> + + <para> + <command>mailimf_fields_parse()</command> parse headers of a + message. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> this is a string containing the header + </para> + </listitem> + <listitem> + <para> + <command>length</command> this is the size of the given string + </para> + </listitem> + <listitem> + <para> + <command>index</command> index this is a pointer to the + start of the header in + the given string, <command>(* index)</command> is + modified to point at the end + of the parsed data + </para> + </listitem> + <listitem> + <para> + <command>result</command> the result of the parse + operation is stored in + <command>(* result)</command> + (see <xref linkend="mailimf-fields">). + </para> + </listitem> + </itemizedlist> + + <para> + return <command>MAILIMF_NO_ERROR</command> on success, + <command>MAILIMF_ERROR_XXX</command> on error. + </para> + + <example> + <title>parsing header fields</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(f); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_ignore_field_parse --> + <sect2 id="mailimf-ignore-field-parse"> + <title>mailimf_ignore_field_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailimf_ignore_field_parse(char * message, size_t length, + size_t * index); + </programlisting> + + <para> + <command>mailimf_ignore_field_parse()</command> skip the + next header. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> this is a string containing the header + </para> + </listitem> + <listitem> + <para> + <command>length</command> this is the size of the given string + </para> + </listitem> + <listitem> + <para> + <command>index</command> index this is a pointer to the + start of the field to skip in + the given string, <command>(* index)</command> is + modified to point at the end + of the parsed data + </para> + </listitem> + </itemizedlist> + + <para> + return <command>MAILIMF_NO_ERROR</command> on success, + <command>MAILIMF_ERROR_XXX</command> on error. + </para> + + <example> + <title>skipping fields</title> + <programlisting> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + size_t current_index; + + current_index = 0; + r = mailimf_ignore_field_parse(mem, stat_info.st_size, + ¤t_index); + if (r == MAILIMF_NO_ERROR) { + /* do the things */ + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailimf_mailbox_list_parse --> + <sect2 id="mailimf-mailbox-list-parse"> + <title>mailimf_mailbox_list_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int +mailimf_mailbox_list_parse(char * message, size_t length, + size_t * index, + struct mailimf_mailbox_list ** result); + </programlisting> + + <para> + <command>mailimf_mailbox_list_parse()</command> parse a list + of mailboxes in RFC 2822 form. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> this is a string containing the + list of mailboxes. + </para> + </listitem> + <listitem> + <para> + <command>length</command> this is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> index this is a pointer to the + start of the list of + mailboxes in the given string, + <command>(* index)</command> is modified to point + at the end of the parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command> the result of the parse + operation is stored in + <command>(* result)</command>. + (see <xref linkend="mailimf-mailbox-list">) + </para> + </listitem> + </itemizedlist> + + <para> + return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on + error. + </para> + + <example> + <title>parsing a list of mailboxes</title> + <programlisting> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_mailbox_list * mb_list; + size_t current_index; + + current_index = 0; + r = mailimf_mailbox_list_parse(mem, stat_info.st_size, + ¤t_index, &mb_list); + if (r == MAILIMF_NO_ERROR) { + display_mailbox_list(mb_list); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_mailbox_list_free(mb_list); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + + </sect2> + + <!-- mailimf_mailbox_parse --> + <sect2 id="mailimf-mailbox-parse"> + <title>mailimf_mailbox_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailimf_mailbox_parse(char * message, size_t length, + size_t * index, + struct mailimf_mailbox ** result); + </programlisting> + + <para> + <command>mailimf_mailbox_parse</command> parse a mailbox in + RFC 2822 form. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> this is a string containing the + mailbox. + </para> + </listitem> + <listitem> + <para> + <command>length</command> this is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> index this is a pointer to the + start of the mailbox in the given string, + <command>(* index)</command> is modified to point + at the end of the parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command> the result of the parse + operation is stored in + <command>(* result)</command>. + (see <xref linkend="mailimf-mailbox">) + </para> + </listitem> + </itemizedlist> + + <para> + return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on + error. + </para> + + <example> + <title>parsing a mailbox</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_mailbox_list * mb_list; + size_t current_index; + + current_index = 0; + r = mailimf_mailbox_parse(mem, stat_info.st_size, + ¤t_index, &mb_list); + if (r == MAILIMF_NO_ERROR) { + display_mailbox_list(mb_list); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_mailbox_free(mb_list); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + + </sect2> + + <!-- mailimf_message_parse --> + <sect2 id="mailimf-message-parse"> + <title>mailimf_message_parse</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailimf_message_parse(char * message, size_t length, + size_t * index, + struct mailimf_message ** result); + </programlisting> + + <para> + <command>mailimf_message_parse</command> parse message + (headers and body). + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> this is a string containing + the message content. + </para> + </listitem> + <listitem> + <para> + <command>param</command> length this is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>param</command> index this is a pointer to the + start of the message in + the given string, <command>(* index)</command> is + modified to point at the end + of the parsed data. + </para> + </listitem> + <listitem> + <para> + <command>param</command> result the result of the parse + operation is stored in + <command>(* result)</command> + (see <xref linkend="mailimf-message">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>parsing a message</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_message * m; + size_t current_index; + + current_index = 0; + r = mailimf_message_parse(mem, stat_info.st_size, + ¤t_index, &m); + if (r == MAILIMF_NO_ERROR) { + display_message(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_message_free(m); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + + </sect2> + </sect1> + + <!-- helper functions --> + <sect1> + <title>Creation functions</title> + <sect2 id="mailimf-mailbox-list-add"> + <title>mailimf_mailbox_list</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new_empty(); + +int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list, + struct mailimf_mailbox * mb); + +int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list, + char * mb_str); + +int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list, + char * display_name, char * address); + </programlisting> + + <!-- mailimf_mailbox_list_new_empty --> + <para> + <command>mailimf_mailbox_list_new_empty()</command> creates a + new empty list of mailboxes. + </para> + + <!-- mailimf_mailbox_list_add --> + <para> + <command>mailimf_mailbox_list_add</command> adds a mailbox + to the list of mailboxes. + </para> + + <!-- mailimf_mailbox_list_add_parse --> + <para> + <command>mailimf_mailbox_list_add_parse</command> adds a + mailbox given in form of a string to the list of mailboxes. + </para> + + <!-- mailimf_mailbox_list_add_mb --> + <para> + <command>mailimf_mailbox_list_add_mb</command> adds a + mailbox given in form of a couple : display name, mailbox + address. + </para> + + <itemizedlist> + <listitem> + <para> + <command>mailbox_list</command> is the list of mailboxes. + </para> + </listitem> + <listitem> + <para> + <command>mb</command> is a mailbox + (see <xref linkend="mailimf-mailbox">). + </para> + </listitem> + <listitem> + <para> + <command>mb_str</command> is a mailbox given in the form + of a string. + </para> + </listitem> + <listitem> + <para> + <command>display_name</command> is the display name. + </para> + </listitem> + <listitem> + <para> + <command>address</command> is the mailbox address. + </para> + </listitem> + </itemizedlist> + + <example> + <title>creating a list of mailboxes</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_mailbox * mb; + + mb_list = mailimf_mailbox_list_new_empty(); + + mb = mailimf_mailbox_new(strdup("DINH Viet Hoa"), + strdup("dinh.viet.hoa@free.fr")); + mailimf_mailbox_list_add(mb_list, mb); + + mailimf_mailbox_list_add_parse(mb_list, "foo bar <foo@bar.org>"); + + mailimf_mailbox_list_add_mb(mb_list, strdup("bar foo"), strdup("bar@foo.com")); + + mailimf_mailbox_list_free(mb_list); +} + </programlisting> + </example> + + </sect2> + <sect2 id="mailimf-address-list-add"> + <title>mailimf_address_list</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_address_list * mailimf_address_list_new_empty(); + +int mailimf_address_list_add(struct mailimf_address_list * address_list, + struct mailimf_address * addr); + +int mailimf_address_list_add_parse(struct mailimf_address_list * address_list, + char * addr_str); + +int mailimf_address_list_add_mb(struct mailimf_address_list * address_list, + char * display_name, char * address); + </programlisting> + + <!-- mailimf_address_list_new_empty --> + <para> + <command>mailimf_address_list_new_empty()</command> creates a + new empty list of addresses. + </para> + + <!-- mailimf_address_list_add --> + <para> + <command>mailimf_address_list_add</command> adds an address + to the list of addresses. + </para> + + <!-- mailimf_address_list_add_parse --> + <para> + <command>mailimf_address_list_add_parse</command> adds an + address given in form of a string to the list of addresses. + </para> + + <!-- mailimf_address_list_add_mb --> + <para> + <command>mailimf_address_list_add_mb</command> adds a + mailbox given in form of a couple : display name, mailbox + address. + </para> + + <itemizedlist> + <listitem> + <para> + <command>address_list</command> is the list of mailboxes. + </para> + </listitem> + <listitem> + <para> + <command>addr</command> is an address. + (see <xref linkend="mailimf-address">). + </para> + </listitem> + <listitem> + <para> + <command>addr_str</command> is an address given in the form of a + string. + </para> + </listitem> + <listitem> + <para> + <command>display_name</command> is the display name. + </para> + </listitem> + <listitem> + <para> + <command>address</command> is the mailbox address. + </para> + </listitem> + </itemizedlist> + + </sect2> + <sect2 id="mailimf-fields-add"> + <title>mailimf_fields</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailimf_fields * +mailimf_fields_new_empty(void); + +struct mailimf_field * mailimf_field_new_custom(char * name, char * value); + +int mailimf_fields_add(struct mailimf_fields * fields, + struct mailimf_field * field); + +int mailimf_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * msg_id, + clist * in_reply_to, + clist * references, + char * subject); + +struct mailimf_fields * +mailimf_fields_new_with_data_all(struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * message_id, + clist * in_reply_to, + clist * references, + char * subject); + +struct mailimf_fields * +mailimf_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + clist * in_reply_to, + clist * references, + char * subject); + +char * mailimf_get_message_id(void); + +struct mailimf_date_time * mailimf_get_current_date(void); + +int +mailimf_resent_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * resent_date, + struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +struct mailimf_fields * +mailimf_resent_fields_new_with_data_all(struct mailimf_date_time * + resent_date, struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +struct mailimf_fields * +mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc); + </programlisting> + + <itemizedlist> + <listitem> + <para> + <command>from</command> is the parsed content of the + From field + (see <xref linkend="mailimf-from">). + </para> + </listitem> + <listitem> + <para> + <command>sender</command> is the parsed content of the + Sender field + (see <xref linkend="mailimf-sender">). + </para> + </listitem> + <listitem> + <para> + <command>reply_to</command> is the parsed content of the + <command>Reply-To</command> field + (see <xref linkend="mailimf-reply-to">). + </para> + </listitem> + <listitem> + <para> + <command>to</command> is the parsed content of the + <command>To</command> field + (see <xref linkend="mailimf-to">). + </para> + </listitem> + <listitem> + <para> + <command>cc</command> is the parsed content of the + <command>Cc</command> field + (see <xref linkend="mailimf-cc">). + </para> + </listitem> + <listitem> + <para> + <command>bcc</command> is the parsed content of the + <command>Bcc</command> field + (see <xref linkend="mailimf-bcc">). + </para> + </listitem> + <listitem> + <para> + <command>message_id</command> is the parsed content of + the <command>Message-ID</command> field + (see <xref linkend="mailimf-message-id">). + </para> + </listitem> + <listitem> + <para> + <command>in_reply_to</command> is the parsed content of + the <command>In-Reply-To</command> field + (see <xref linkend="mailimf-in-reply-to">). + </para> + </listitem> + <listitem> + <para> + <command>references</command> is the parsed content of + the <command>References</command> field + (see <xref linkend="mailimf-references">). + </para> + </listitem> + <listitem> + <para> + <command>subject</command> is the content of the + <command>Subject</command> field + (see <xref linkend="mailimf-subject">). + </para> + </listitem> + <listitem> + <para> + <command>resent_date</command> is the parsed content of + the <command>Resent-Date</command> field + (see <xref linkend="mailimf-orig-date">). + </para> + </listitem> + <listitem> + <para> + <command>resent_from</command> is the parsed content of + the <command>Resent-From</command> field + (see <xref linkend="mailimf-from">). + </para> + </listitem> + <listitem> + <para> + <command>resent_sender</command> is the parsed content of the + <command>Resent-Sender</command> field + (see <xref linkend="mailimf-sender">). + </para> + </listitem> + <listitem> + <para> + <command>resent_to</command> is the parsed content of + the <command>Resent-To</command> field + (see <xref linkend="mailimf-to">). + </para> + </listitem> + <listitem> + <para> + <command>resent_cc</command> is the parsed content of + the <command>Resent-Cc</command> field + (see <xref linkend="mailimf-cc">). + </para> + </listitem> + <listitem> + <para> + <command>resent_bcc</command> is the parsed content of the + <command>Resent-Bcc</command> field + (see <xref linkend="mailimf-bcc">). + </para> + </listitem> + <listitem> + <para> + <command>resent_msg_id</command> is the parsed content of the + <command>Resent-Message-ID</command> field + (see <xref linkend="mailimf-message-id">). + </para> + </listitem> + </itemizedlist> + + <!-- mailimf_fields_new_empty --> + <para> + <command>mailimf_fields_new_empty()</command> creates a new + empty set of headers. + </para> + + <!-- mailimf_fields_new_custom --> + <para> + <command>mailimf_field_new_custom()</command> creates a new + custom header. + </para> + + <!-- mailimf_fields_add --> + <para> + <command>mailimf_fields_add()</command> adds a header to the + set of headers. + </para> + + <!-- mailimf_fields_add_data --> + <para> + <command>mailimf_fields_add_data()</command> adds some headers + to the set of headers. + </para> + + <!-- mailimf_fields_new_with_data_all --> + <para> + <command>mailimf_fields_new_with_data_all()</command> creates + a set of headers with some headers (including Date and + Message-ID). + </para> + + <!-- mailimf_fields_new_with_data --> + <para> + <command>mailimf_fields_new_with_data()</command> creates a + set of headers with some headers (Date and Message-ID will + be generated). + </para> + + <!-- mailimf_get_message_id --> + <para> + <command>mailimf_get_message_id()</command> generates a + Message-ID. The result must be freed using + <command>free()</command>. + </para> + + <!-- mailimf_get_current_date --> + <para> + <command>mailimf_get_current_date()</command> generates a + Date. The result must be freed using + <command>mailimf_date_time_free</command>. + </para> + + <!-- mailimf_resent_fields_add_data --> + <para> + <command>mailimf_resent_fields_add_data()</command> adds some + resent headers to the set of headers. + </para> + + <!-- mailimf_resent_fields_new_with_data_all --> + <para> + <command>mailimf_resent_fields_new_with_data_all()</command> + creates a set of headers with some resent headers (including + Resent-Date and Resent-Message-ID). + </para> + + <!-- mailimf_resent_fields_new_with_data --> + <para> + <command>mailimf_resent_fields_new_with_data()</command> + creates a set of headers with some resent headers + (Resent-Date and Resent-Message-ID will be generated) + </para> + + <example> + <title>creation of header fields</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_field * field; + struct mailimf_date_time * date; + char * msg_id; + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + + fields = mailimf_fields_new_empty(); + field = mailimf_field_new_custom(strdup("X-Mailer"), strdup("my-mailer")); + mailimf_fields_add(fields, field); + + from = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet.hoa@free.fr"); + date = mailimf_get_current_date(); + msg_id = mailimf_get_message_id(); + to = mailimf_address_list_new_empty(); + mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org"); + + mailimf_fields_add_data(fields, date, from, NULL, NULL, to, NULL, NULL, + msg_id, NULL, NULL, strdup("hello")); + + /* do the things */ + + mailimf_fields_free(fields); +} + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + struct mailimf_date_time * date; + char * msg_id; + + from = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet.hoa@free.fr"); + to = mailimf_address_list_new_empty(); + mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org"); + date = mailimf_get_current_date(); + msg_id = mailimf_get_message_id(); + + fields = mailimf_fields_new_with_all_data(date, from, NULL, NULL, to, NULL, NULL, + msg_id, NULL, NULL, strdup("hello")); + + /* do the things */ + + mailimf_fields_free(fields); +} + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + + from = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet.hoa@free.fr"); + to = mailimf_address_list_new_empty(); + mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org"); + + fields = mailimf_fields_new_with_data(from, NULL, NULL, to, NULL, NULL, + NULL, NULL, strdup("hello")); + + /* do the things */ + + mailimf_fields_free(fields); +} + </programlisting> + </example> + </sect2> + </sect1> + + <!-- rendering functions --> + <sect1> + <title>Rendering of messages</title> + <sect2 id="mailimf-fields-write"> + <title>Header fields</title> + <programlisting> +#include <libetpan/libetpan.h> + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field); + </programlisting> + + <itemizedlist> + <listitem> + <para> + <command>col</command> current column is given for wrapping + purpose in <command>(* col)</command>, + the resulting columns will be returned.. + </para> + </listitem> + <listitem> + <para> + <command>f</command> is the file descriptor. It can be + stdout for example. + </para> + </listitem> + <listitem> + <para> + <command>fields</command> is the header fields + (see <xref linkend="mailimf-fields">). + </para> + </listitem> + <listitem> + <para> + <command>field</command> is a field + (see <xref linkend="mailimf-field">). + </para> + </listitem> + </itemizedlist> + + <!-- mailimf_fields_write --> + <para> + <command>mailimf_fields_write</command> outputs the set of + header fields. + </para> + + <!-- mailimf_envelope_fields_write --> + <para> + <command>mailimf_envelope_fields_write</command> outputs the + set of header fields except the optional fields. + </para> + + <!-- mailimf_field_write --> + <para> + <command>mailimf_field_write</command> outputs a header. + </para> + + <example> + <title>rendering of fields</title> + <programlisting role="C"> +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + int col; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_imf_fields(); + + col = 0; + mailimf_fields_write(stdout, &col, fields); + + mailimf_fields_free(fields); +} + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + int col; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_imf_fields(); + + col = 0; + mailimf_envelope_fields_write(stdout, &col, fields); + + mailimf_fields_free(fields); +} + +int main(int argc, char ** argv) +{ + struct mailimf_field * field; + int col; + + field = mailimf_field_new_custom(strdup("X-Mailer"), strdup("my mailer")); + + col = 0; + mailimf_field_write(stdout, &col, field); + + mailimf_field_free(field); +} + </programlisting> + </example> + </sect2> + </sect1> + </chapter> + + + <!-- MIME --> + <chapter> + <title>MIME</title> + + <para> + libEtPan! implements a MIME message parser (also known as + messages with attachments or + multipart messages). This also allows to generate MIME messages. + </para> + + <warning> + <para> + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + </para> + + <para> + allocation functions will return <command>NULL</command> on failure + + functions returning integer will be returning one of the + following error code: + <command>MAILIMF_NO_ERROR</command>, + <command>MAILIMF_ERROR_PARSE</command>, + <command>MAILIMF_ERROR_MEMORY</command>, + <command>MAILIMF_ERROR_INVAL</command>, + or <command>MAILIMF_ERROR_FILE</command>. + </para> + </warning> + + <sect1> + <title>Quick start</title> + + <para> + You will need this module when you want to parse a MIME + message. + </para> + + <sect2> + <title>Parse MIME message</title> + <para> + You will use the following function : + </para> + <itemizedlist> + <listitem> + <para> + <command>mailmime_parse</command> + (<xref linkend="mailimf-envelope-and-optional-fields-parse">) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Render the MIME message</title> + <para> + Build your MIME message, then use + <command>mailmime_write</command> + (<xref linkend="mailmime-write">) + to render a MIME message. + </sect2> + </sect1> + + <!-- Data types--> + <sect1> + <title>Data types</title> + <!-- mailmime_composite_type --> + <sect2 id="mailmime-composite-type"> + <title>mailmime_composite_type - Composite MIME type</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +enum { + MAILMIME_COMPOSITE_TYPE_ERROR, + MAILMIME_COMPOSITE_TYPE_MESSAGE, + MAILMIME_COMPOSITE_TYPE_MULTIPART, + MAILMIME_COMPOSITE_TYPE_EXTENSION +}; + +struct mailmime_composite_type { + int ct_type; + char * ct_token; +}; + +struct mailmime_composite_type * +mailmime_composite_type_new(int ct_type, char * ct_token); + +void mailmime_composite_type_free(struct mailmime_composite_type * ct); + </programlisting> + + <para> + This is a MIME composite type such as <command>message</command> or + <command>multipart</command>. + </para> + + <para> + <command>ct_type</command> can have one of the 3 following values : + <command>MAILMIME_COMPOSITE_TYPE_MESSAGE</command> when the + composite MIME type + is <command>message</command>, + <command>MAILMIME_COMPOSITE_TYPE_MULTIPART</command> when + the composite MIME type + is <command> multipart</command>, + <command>MAILMIME_COMPOSITE_TYPE_EXTENSION</command> for + other and <command>ct_token</command> is set + in this case. + <command>MAILMIME_COMPOSITE_TYPE_ERROR</command> is used + internally on parse error. + </para> + + <para> + <command>mailmime_composite_type_new()</command> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailmime_composite_type_free()</command> frees + memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>create and display MIME composite type</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(void) +{ + struct mailmime_composite_type * ct; + + ct = mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL); + + /* do your things ... */ + + mailmime_composite_type_free(ct); + + exit(EXIT_SUCCESS); +} + +void display_composite_type() +{ + switch (ct->type) { + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + printf("composite type is message\n"); + break; + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + printf("composite type is multipart\n"); + break; + case MAILMIME_COMPOSITE_TYPE_EXTENSION: + printf("composite type: %s\n", ct->ct_token); + break; + } +} + </programlisting> + </example> + + </sect2> + + <!-- mailmime_content --> + <sect2 id="mailmime-content"> + <title>mailmime_content - MIME content type (Content-Type)</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailmime_content { + struct mailmime_type * ct_type; + char * ct_subtype; + clist * ct_parameters; /* elements are (struct mailmime_parameter *) */ +}; + +struct mailmime_content * +mailmime_content_new(struct mailmime_type * ct_type, + char * ct_subtype, + clist * ct_parameters); + +void mailmime_content_free(struct mailmime_content * content); + </programlisting> + + <para> + This is a MIME content type such as <command>message/rfc822</command> or + <command>text/plain</command>. + </para> + + <itemizedlist> + <listitem> + <para> + <command>ct_type</command> is the main MIME type, + for example <command>text</command> in + <command>plain/text</command> + (see <xref linkend="mailmime-type">). + </para> + <para> + <command>ct_subtype</command> is the MIME subtype, + for example <command>plain</command> in + <command>plain/text</command>. + </para> + </listitem> + <listitem> + <para> + <command>ct_parameters</command> is the list of parameters for + the given MIME type. For example, for <command>plain/text</command>, + we can find <command>charset=iso-8859-1</command>, + <command>format=flowed</command>. Each element of the list + if of type <command>struct mailmime_parameter *</command> + (see <xref linkend="mailmime-parameter">). + </para> + </listitem> + </itemizedlist> + + <para> + <command>mailmime_content_new()</command> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailmime_content_free()</command> frees memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>Creation and display of MIME content type</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(void) +{ + struct mailmime_content * content; + struct mailmime_type * type; + struct mailmime_discrete_type * dt; + struct mailmime_parameter * param; + clist * param_list; + + dt = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, NULL); + type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, dt, NUL); + param_list = clist_new(); + param = mailmime_parameter_new(strdup("charset"), strdup("iso-8859-1")); + clist_append(param_list, param); + + content = mailmime_content_new(type, strdup("plain"), param_list); + + /* do your things */ + + exit(EXIT_SUCCESS); +} + +void display_mime_content(struct mailmime_content * content_type) +{ + clistiter * cur; + + printf("type:\n"); + display_type(content_type->ct_type); + printf("\n"); + printf("subtype: %s\n", content_type->ct_subtype); + printf("\n"); + + for(cur = clist_begin(content_type->ct_parameters) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + display_mime_parameter(param); + printf("\n"); + } + printf("\n"); +} + </programlisting> + </example> + + </sect2> + + <!-- mailmime_discrete_type --> + <sect2 id="mailmime-discrete-type"> + <title>mailmime_discrete_type - MIME discrete type</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISCRETE_TYPE_ERROR, + MAILMIME_DISCRETE_TYPE_TEXT, + MAILMIME_DISCRETE_TYPE_IMAGE, + MAILMIME_DISCRETE_TYPE_AUDIO, + MAILMIME_DISCRETE_TYPE_VIDEO, + MAILMIME_DISCRETE_TYPE_APPLICATION, + MAILMIME_DISCRETE_TYPE_EXTENSION +}; + +struct mailmime_discrete_type { + int dt_type; + char * dt_extension; +}; + +struct mailmime_discrete_type * +mailmime_discrete_type_new(int dt_type, char * dt_extension); + +void mailmime_discrete_type_free(struct mailmime_discrete_type * + discrete_type); + </programlisting> + + <para> + This is a MIME discrete type such as <command>text</command> or + <command>image</command>. This is also known as single part. This kind + of part does not have any child. + </para> + + <para> + <command>dt_type</command> is one of the given values : + <command>MAILMIME_DISCRETE_TYPE_TEXT</command> if part is text, + <command>MAILMIME_DISCRETE_TYPE_IMAGE</command> if part is an image, + <command>MAILMIME_DISCRETE_TYPE_AUDIO</command> if part is + audio data, + <command>MAILMIME_DISCRETE_TYPE_VIDEO</command> if part is video, + <command>MAILMIME_DISCRETE_TYPE_APPLICATION</command> if + part is application data or + <command>MAILMIME_DISCRETE_TYPE_EXTENSION</command> for other. + In the case of <command>MAILMIME_DISCRETE_TYPE_EXTENSION</command>, + <command>dt_extension</command> is filled in. + <command>MAILMIME_DISCRETE_TYPE_ERROR</command> is used internally. + </para> + + <para> + <command>mailmime_discrete_type_new()</command> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailmime_discrete_type_free()</command> frees + memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>Creation and display of MIME discrete type</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +/* standard type */ + +int main(int argc, char ** argv) +{ + struct mailmime_discrete_type * discrete_type; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, + NULL); + + /* do the things */ + + mailmime_discrete_type_free(discrete_type); +} + +/* extension */ + +int main(int argc, char ** argv) +{ + struct mailmime_discrete_type * discrete_type; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_EXTENSION, + strdup("my-type")); + + /* do the things */ + + mailmime_discrete_type_free(discrete_type); +} + +void display_mime_discrete_type(struct mailmime_discrete_type * discrete_type) +{ + switch (discrete_type->dt_type) { + case MAILMIME_DISCRETE_TYPE_TEXT: + printf("text\n"); + break; + case MAILMIME_DISCRETE_TYPE_IMAGE: + printf("image\n"); + break; + case MAILMIME_DISCRETE_TYPE_AUDIO: + printf("audio\n"); + break; + case MAILMIME_DISCRETE_TYPE_VIDEO: + printf("video\n"); + break; + case MAILMIME_DISCRETE_TYPE_APPLICATION: + printf("application\n"); + break; + case MAILMIME_DISCRETE_TYPE_EXTENSION: + printf("extension : %s\n", discrete_type->dt_extension); + break; + } +} + </programlisting> + </example> + + </sect2> + + <!-- mailmime_field --> + <sect2 id="mailmime-field"> + <title>mailmime_field - MIME header field</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +enum { + MAILMIME_FIELD_NONE, + MAILMIME_FIELD_TYPE, + MAILMIME_FIELD_TRANSFER_ENCODING, + MAILMIME_FIELD_ID, + MAILMIME_FIELD_DESCRIPTION, + MAILMIME_FIELD_VERSION, + MAILMIME_FIELD_DISPOSITION, + MAILMIME_FIELD_LANGUAGE, +}; + +struct mailmime_field { + int fld_type; + union { + struct mailmime_content * fld_content; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + struct mailmime_language * fld_language; + } fld_data; +}; + +struct mailmime_field * +mailmime_field_new(int fld_type, + struct mailmime_content * fld_content, + struct mailmime_mechanism * fld_encoding, + char * fld_id, + char * fld_description, + uint32_t fld_version, + struct mailmime_disposition * fld_disposition, + struct mailmime_language * fld_language); + +void mailmime_field_free(struct mailmime_field * field); + </programlisting> + + <para> + This is a parsed MIME header field; + </para> + + <itemizedlist> + <listitem> + <para> + <command>fld_type</command> is the type of MIME header field. The value can + be + <command>MAILMIME_FIELD_TYPE</command> + if field is <command>Content-Type</command>, + <command>MAILMIME_FIELD_TRANSFER_ENCODING</command> + if field is <command>Content-Transfer-Encoding</command>, + <command>MAILMIME_FIELD_ID</command> + if field is <command>Content-ID</command>, + <command>MAILMIME_FIELD_DESCRIPTION</command> + if field is <command>Content-Description</command>, + <command>MAILMIME_FIELD_VERSION</command> + if field is <command>MIME-Version</command>, + <command>MAILMIME_FIELD_DISPOSITION</command> + if field is <command>Content-Disposition</command> or + <command>MAILMIME_FIELD_LANGUAGE</command> + if field is <command>Content-Language</command>. + <command>MAILMIME_FIELD_NONE</command> is used internally. + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_content</command> is set in case of + <command>Content-Type</command>. + (see <xref linkend="mailmime-content">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_encoding</command> is set in case of + <command>Content-Transfer-Encoding</command>. + (see <xref linkend="mailmime-mechanism">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_id</command> is set in case of + <command>Content-ID</command>. This is a string. + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_description</command> is set in case of + <command>Content-Description</command>. This is a string. + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_version</command> is set in case of + <command>MIME-Version</command>. This is an integer built + using the following formula : + <command>fld_version = major * 2^16 + minor</command>. + Currenly MIME-Version is always <command>1.0</command>, this means that + fld_version will always be <command>2^16</command> (in C language, + this is <command>1 << 16</command>). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_disposition</command> is set in case of + <command>Content-Disposition</command>. + (see <xref linkend="mailmime-disposition">). + </para> + </listitem> + <listitem> + <para> + <command>fld_data.fld_language</command> is set in case of + <command>Content-Language</command>. + (see <xref linkend="mailmime-language">). + </para> + </listitem> + </itemizedlist> + + <para> + <command>mailmime_field_new()</command> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailmime_field_free()</command> frees memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>Creation and display of MIME header field</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_field * field; + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL); + + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, encoding, NULL, NULL, 0, NULL, NULL); + + /* do the things */ + + mailmime_field_free(field); +} + +void display_mime_field(struct mailmime_field * field) +{ + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + printf("content-type:"); + display_mime_content(field->fld_data.fld_content); + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + printf("content-transfer-encoding:"); + display_mime_mechanism(field->fld_data.fld_encoding); + break; + case MAILMIME_FIELD_ID: + printf("content-id: %s\n", field->fld_data.fld_id); + break; + case MAILMIME_FIELD_DESCRIPTION: + printf("content-description: %s\n", field->fld_data.fld_description); + break; + case MAILMIME_FIELD_VERSION: + printf("mime-version: %i.%i\n", + field->version>> 16, field->fld_data.fld_version & 0xFFFF); + break; + case MAILMIME_FIELD_DISPOSITION: + printf("content-disposition:"); + display_mime_disposition(field->fld_data.fld_disposition); + break; + case MAILMIME_FIELD_LANGUAGE: + printf("content-language:"); + display_mime_language(field->fld_data.fld_language); + break; + } +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_mechanism --> + <sect2 id="mailmime-mechanism"> + <title>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_mechanism { + int enc_type; + char * enc_token; +}; + +struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token); + +void mailmime_mechanism_free(struct mailmime_mechanism * mechanism); + </programlisting> + + <para> + This is a MIME transfer encoding mechanism description. + </para> + + <para> + <command>enc_type</command> is an encoding type. The value of this field + can be + <command>MAILMIME_MECHANISM_7BIT</command> + if mechanism is <command>7bit</command>, + <command>MAILMIME_MECHANISM_8BIT</command> + if mechanism is <command>8bit</command>, + <command>MAILMIME_MECHANISM_BINARY</command> + if mechanism is <command>binary</command>, + <command>MAILMIME_MECHANISM_QUOTED_PRINTABLE</command> + if mechanism is <command>quoted-printable</command>, + <command>MAILMIME_MECHANISM_BASE64</command> + if mechanism is <command>base64</command> or + <command>MAILMIME_MECHANISM_TOKEN</command> for other. + In case of <command>MAILMIME_MECHANISM_TOKEN</command>, + field <command>enc_token</command> is filled in. + <command>MAILMIME_MECHANISM_ERROR</command> is used internally. + </para> + + <para> + <command>mailmime_mechanism_new()</command> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailmime_mechanism_free()</command> frees memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>Creation and display of MIME transfer encoding mechanism</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_QUOTED_PRINTABLE, NULL); + + /* do the things */ + + mailmime_mechanism_free(encoding); +} + +int main(int argc, char ** argv) +{ + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_TOKEN, + strdup("uuencoding")); + + /* do the things */ + + mailmime_mechanism_free(encoding); +} + +void display_mime_mechanism(struct mailmime_mechanism * encoding) +{ + switch (encoding->enc_type) { + case MAILMIME_MECHANISM_7BIT: + printf("7bit\n"); + break; + case MAILMIME_MECHANISM_8BIT: + printf("8bit\n"); + break; + case MAILMIME_MECHANISM_BINARY: + printf("binary\n"); + break; + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + printf("quoted-printable\n"); + break; + case MAILMIME_MECHANISM_BASE64: + printf("base64\n"); + break; + case MAILMIME_MECHANISM_TOKEN: + printf("extension : %s\n", encoding->enc_token); + break; + } +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_fields --> + <sect2 id="mailmime-fields"> + <title>mailmime_fields - header fields</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailmime_fields { + clist * fld_list; /* list of (struct mailmime_field *) */ +}; + +struct mailmime_fields * mailmime_fields_new(clist * fld_list); + +void mailmime_fields_free(struct mailmime_fields * fields); + </programlisting> + + <para> + This is the header fields of a MIME part. + </para> + + <para> + <command>fld_list</command> is the list of the header fields. + Each element of the list is a <command>mailmime_field</command> + (See <xref linkend="mailmime-field">). + </para> + + <para> + <command>mailmime_fields_new()</command> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailmime_fields_free()</command> frees memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>Creation and display of MIME fields</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_field * field; + struct mailmime_fields * fields; + clist * list; + struct mailmime_mechanism * encoding; + struct mailmime_disposition * disposition; + + list = clist_new(); + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL); + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, encoding, NULL, NULL, 0, NULL, NULL); + clist_append(list, field); + + field = mailmime_field_new(MAILMIME_FIELD_VERSION, + NULL, NULL, NULL, NULL, 1 << 16, NULL, NULL); + clist_append(list, field); + + /* look at the example in mailmime_disposition to see how to + build a mailmime_disposition */ + disposition = build_mime_disposition(); + field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION, + NULL, NULL, NULL, NULL, 0, disposition, NULL); + clist_append(list, field); + + fields = mailmime_fields_new(list); + + /* do the things */ + + mailmime_fields_free(fields); +} + +void display_mime_fields(struct mailmime_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + display_field(field); + } +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_parameter --> + <sect2 id="mailmime-parameter"> + <title>mailmime_parameter - MIME type parameter</title> + + <programlisting role="C"> +struct mailmime_parameter { + char * pa_name; + char * pa_value; +}; + </programlisting> + + <para> + This is the MIME type parameter in + <command>Content-Type</command> MIME header + field. For example, this can be + <command>charset="iso-8859-1"</command>. + </para> + + <itemizedlist> + <listitem> + <para> + <command>pa_name</command> is the name of the parameter, + for example : <command>charset</command>. + </para> + </listitem> + <listitem> + <para> + <command>pa_value</command> is the value of the parameter, + for example : <command>iso-8859-1</command>. + </para> + </listitem> + </itemizedlist> + + <para> + <command>mailmime_parameter_new()</command> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailmime_parameter_free()</command> frees memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>Creation and display of MIME type parameter</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_parameter * param; + + param = mailmime_parameter_new(strdup("charset"), strdup("iso-8859-1")); + + /* do the things */ + + mailmime_parameter_free(param); +} + +void display_mime_parameter(struct mailmime_parameter * param) +{ + printf("%s = %s\n", param->pa_name, param->pa_value); +} + </programlisting> + </example> + + </sect2> + + <!-- mailmime_type --> + <sect2 id="mailmime-type"> + <title>mailmime_type - MIME main type</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +enum { + MAILMIME_TYPE_ERROR, + MAILMIME_TYPE_DISCRETE_TYPE, + MAILMIME_TYPE_COMPOSITE_TYPE +}; + +struct mailmime_type { + int tp_type; + union { + struct mailmime_discrete_type * tp_discrete_type; + struct mailmime_composite_type * tp_composite_type; + } tp_data; +}; + +struct mailmime_type * +mailmime_type_new(int tp_type, + struct mailmime_discrete_type * tp_discrete_type, + struct mailmime_composite_type * tp_composite_type); + +void mailmime_type_free(struct mailmime_type * type); + </programlisting> + + <para> + This is the MIME main type (no subtype, no parameter). + </para> + + <itemizedlist> + <listitem> + <para> + <command>tp_type</command>. The value of this field + is either <command>MAILMIME_TYPE_DISCRETE_TYPE</command> for MIME discrete type, + or <command>MAILMIME_TYPE_COMPOSITE_TYPE</command> for MIME composite type. + <command>MAILMIME_TYPE_ERROR</command> is used internally. + </para> + </listitem> + <listitem> + <para> + <command>tp_data.tp_discrete_type</command> is set when <command>tp_type</command> + is <command>MAILMIME_TYPE_DISCRETE_TYPE</command> + (see <xref linkend="mailmime-discrete-type">). + </para> + </listitem> + <listitem> + <para> + <command>tp_data.tp_composite_type</command> is set when <command>tp_type</command> + is <command>MAILMIME_TYPE_COMPOSITE_TYPE</command> + (see <xref linkend="mailmime-composite-type">). + </para> + </listitem> + </itemizedlist> + + <para> + <command>mailmime_discrete_type_new()</command> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailmime_discrete_type_free()</command> frees + memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>Creation and display of MIME main type</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_type * type; + struct mailmime_discrete_type * discrete_type; + + discrete_type = + mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, NULL); + type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, discrete_type, NULL); + + /* do the things */ + + mailmime_type_free(type); +} + +int main(int argc, char ** argv) +{ + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, composite_type); + + /* do the things */ + + mailmime_type_free(type); +} + +void display_mime_type(struct mailmime_type * type) +{ + printf("mime type:\n"); + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + printf("discrete type:\n"); + display_mime_discrete_type(type->tp_data.tp_discrete_type); + break; + case MAILMIME_TYPE_COMPOSITE_TYPE: + printf("composite type:\n"); + display_mime_composite_type(type->tp_data.tp_composite_type); + break; + } + printf("\n"); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_discrete_type --> + <sect2 id="mailmime-language"> + <title>mailmime_language - Language of MIME part</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailmime_language { + clist * lg_list; /* atom (char *) */ +}; + +struct mailmime_language * mailmime_language_new(clist * lg_list); + +void mailmime_language_free(struct mailmime_language * lang); + </programlisting> + + <para> + This is the language used in the MIME part. + </para> + + <para> + <command>lg_list</command> is the list of codes of languages used + in the MIME part. This is a list of strings. + </para> + + <para> + <command>mailmime_language_new()</command> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailmime_language_free()</command> frees + memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>Creation and display of language of MIME part</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_language * language; + clist * list; + + list = clist_new(); + + clist_append(list, strdup("fr")); + clist_append(list, strdup("en")); + + language = mailmime_language_new(list); + + /* do the things */ + + mailmime_language_free(language); +} + +void display_mime_language(struct mailmime_language * language) +{ + clistiter * cur; + + printf("languages: "); + for(cur = clist_begin(language->lg_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * name; + + name = clist_content(cur); + printf("%s ", name); + } + printf("\n"); +} + </programlisting> + </example> + + </sect2> + + <!-- mailmime_data --> + <sect2 id="mailmime-data"> + <title>mailmime_data - Content of MIME part</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +enum { + MAILMIME_DATA_TEXT, + MAILMIME_DATA_FILE, +}; + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_data { + int dt_type; + int dt_encoding; + int dt_encoded; + union { + struct { + const char * dt_data; + size_t dt_length; + } dt_text; + char * dt_filename; + } dt_data; +}; + +struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, + int dt_encoded, const char * dt_data, size_t dt_length, + char * dt_filename); + +void mailmime_data_free(struct mailmime_data * mime_ </programlisting> + + <para> + This is the content of MIME part, content of + preamble or content of epilogue. + </para> + + <para> + <command>dt_type</command> can be + <command>MAILMIME_DATA_TEXT</command> if + the content is a string in memory, + <command>MAILMIME_DATA_FILE</command> if the + content is in a file, + </para> + + <para> + <command>dt_encoding</command> is the encoding mechanism + of the part. The value of this field can be + <command>MAILMIME_MECHANISM_7BIT</command> if mechanism is + <command>7bit</command>, + <command>MAILMIME_MECHANISM_8BIT</command> if mechanism is + <command>8bit</command>, + <command>MAILMIME_MECHANISM_BINARY</command> if mechanism is + <command>binary</command>, + <command>MAILMIME_MECHANISM_QUOTED_PRINTABLE</command> if + mechanism is <command>quoted-printable</command>, + <command>MAILMIME_MECHANISM_BASE64</command> if mechanism is + <command>base64</command> or + <command>MAILMIME_MECHANISM_TOKEN</command> for other. If + <command>MAILMIME_MECHANISM_TOKEN</command>, the part will + be considered as binary. + <command>MAILMIME_MECHANISM_ERROR</command> is used internally. + </para> + + <para> + <command>dt_encoded</command> is set to 1 if the part is + already encoded with the mechanism given in + <command>dt_encoding</command>. It is set to 0 if the part + is already decoded or if it is necessary to encode that part + before rendering it. + </para> + + <para> + <command>dt_data.dt_text.dt_data</command> is a pointer to the + content of the part and <command>dt_data.dt_text.dt_length</command> + is the length of the data if <command>dt_type</command> is + <command>MAILMIME_DATA_TEXT</command>. + </para> + + <para> + <command>dt_data.dt_filename</command> is the name of the file if + <command>dt_type</command> is <command>MAILMIME_DATA_FILE</command>. + </para> + + <para> + <command>mailmime_data_new()</command> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailmime_data_free()</command> frees + memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>Creation and display of MIME part content</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +/* build data with a string */ + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_BASE64, + 0, "foo bar", 7, NULL); + + /* do the things */ + + mailmime_data_free(data); +} + +/* build data with a file */ + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_BASE64, + 0, NULL, 0, strdup("foo.txt")); + + /* do the things */ + + mailmime_data_free(data); +} + +void display_mime_data(struct mailmime_data * data) +{ + switch (data->dt_encoding) { + case MAILMIME_MECHANISM_7BIT: + printf("7bit\n"); + break; + case MAILMIME_MECHANISM_8BIT: + printf("8bit\n"); + break; + case MAILMIME_MECHANISM_BINARY: + printf("binary\n"); + break; + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + printf("quoted-printable\n"); + break; + case MAILMIME_MECHANISM_BASE64: + printf("base64\n"); + break; + case MAILMIME_MECHANISM_TOKEN: + printf("other\n"); + break; + } + + if (data->dt_encoded) + printf("already encoded\n"); + else + printf("not encoded\n"); + + switch (data->dt_type) { + MAILMIME_DATA_TEXT: + printf("data : %p %i\n", data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length); + break; + MAILMIME_DATA_FILE, + printf("data (file) : %s\n", data->dt_data.dt_filename); + break; + } +} + </programlisting> + </example> + </sect2> + + <!-- mailmime --> + <sect2 id="mailmime"> + <title>mailmime - MIME part</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +enum { + MAILMIME_NONE, + MAILMIME_SINGLE, + MAILMIME_MULTIPLE, + MAILMIME_MESSAGE, +}; + +struct mailmime { + /* parent information */ + int mm_parent_type; + struct mailmime * mm_parent; + clistiter * mm_multipart_pos; + + int mm_type; + const char * mm_mime_start; + size_t mm_length; + + struct mailmime_fields * mm_mime_fields; + struct mailmime_content * mm_content_type; + + struct mailmime_data * mm_body; + union { + /* single part */ + struct mailmime_data * mm_single; /* XXX - was body */ + + /* multi-part */ + struct { + struct mailmime_data * mm_preamble; + struct mailmime_data * mm_epilogue; + clist * mm_mp_list; + } mm_multipart; + + /* message */ + struct { + struct mailimf_fields * mm_fields; + struct mailmime * mm_msg_mime; + } mm_message; + + } mm_data; +}; + +struct mailmime * mailmime_new(int mm_type, + const char * mm_mime_start, size_t mm_length, + struct mailmime_fields * mm_mime_fields, + struct mailmime_content * mm_content_type, + struct mailmime_data * mm_body, + struct mailmime_data * mm_preamble, + struct mailmime_data * mm_epilogue, + clist * mm_mp_list, + struct mailimf_fields * mm_fields, + struct mailmime * mm_msg_mime); + +void mailmime_free(struct mailmime * mime); + </programlisting> + + <para> + This describes the MIME structure of a message or a subpart + of a message. + </para> + + <sect3> + <title>common</title> + + <itemizedlist> + <listitem> + <para> + <command>mm_parent_type</command>. MIME part type can be + single part, multipart or message part. This describes the MIME part + type of the parent. The value can be + <command>MAILMIME_NONE</command> if there is no parent part, + <command>MAILMIME_SINGLE</command> if parent is a single part, + <command>MAILMIME_MULTIPLE</command> if parent is a multipart, + <command>MAILMIME_MESSAGE</command> if parent is a mesage part. + </para> + </listitem> + + <listitem> + <para> + <command>mm_parent</command> is the parent MIME structure. + </para> + </listitem> + + <listitem> + <para> + <command>mm_multipart_pos</command>. In the case the parent + is a multipart. This is the position in the list of children + of the parent. This position is given by a + <command>clisiter *</command>. + </para> + </listitem> + + <listitem> + <para> + <command>mm_type</command>. This describes the MIME part type + of this part. The value can be + <command>MAILMIME_SINGLE</command> if this is a single part, + <command>MAILMIME_MULTIPLE</command> if this is a multipart, + <command>MAILMIME_MESSAGE</command> if this is a mesage part. + </para> + </listitem> + + <listitem> + <para> + <command>mm_mime_start</command>. This is used mostly internally. + This gives the beginning of the header of the MIME part, when this + is parsed from a string in memory. + </para> + </listitem> + + + <listitem> + <para> + <command>mm_length</command>. This gives the length of the MIME part, + including the MIME header fields. + </para> + </listitem> + + <listitem> + <para> + <command>mm_mime_fields</command> is the list of parsed MIME headers + of this part. <command>Content-Type</command> must be excluded and stored + in <command>mm_content_type</command> instead + (see <xref linkend="mailmime-fields">). + </para> + </listitem> + + + <listitem> + <para> + <command>mm_content_type</command> is the parsed + <command>Content-Type</command> field + (see <xref linkend="mailmime-content">). + </para> + </listitem> + + + <listitem> + <para> + <command>mm_body</command> is the content of the MIME part + (excluding MIME header), when it is parsed from a string + in memory + (see <xref linkend="mailmime-data">). + </para> + </listitem> + </itemizedlist> + </sect3> + + <sect3> + <title>single part</title> + + <itemizedlist> + <listitem> + <para> + When the part is a single part (<command>mm_type</command> + is <command>MAILMIME_SINGLE</command>). The following fields + are valid. + </para> + </listitem> + + <listitem> + <para> + <command>mm_data.mm_single</command> is the content of the + MIME part (excluding MIME header), when it is parsed from a string + in memory. This must have the same + value as <command>mm_body</command> when it is set + (see <xref linkend="mailmime-data">). + </para> + </listitem> + </itemizedlist> + </sect3> + + <sect3> + <title>multipart</title> + + <itemizedlist> + <listitem> + <para> + When the part is a multipart (<command>mm_type</command> + is <command>MAILMIME_MULTIPLE</command>). The following fields + are valid. + </para> + </listitem> + + <listitem> + <para> + <command>mm_data.mm_multipart.mm_preamble</command> + is the content of the preamble of the multipart + (see <xref linkend="mailmime-data">). + </para> + </listitem> + + <listitem> + <para> + <command>mm_data.mm_multipart.mm_epilogue</command> + is the content of the epilogue of the multipart + (see <xref linkend="mailmime-data">). + </para> + </listitem> + + <listitem> + <para> + <command>mm_data.mm_multipart.mm_mp_list</command> + is the list of sub parts + </para> + </listitem> + </itemizedlist> + </sect3> + + <sect3> + <title>message part</title> + + <itemizedlist> + <listitem> + <para> + When the part is a message (<command>mm_type</command> + is <command>MAILMIME_MESSAGE</command>). The following fields + are valid. + </para> + </listitem> + + <listitem> + <para> + <command>mm_data.mm_message.mm_fields</command> is the list of + the header fields of the message + (see <xref linkend="mailimf-fields">). + </para> + </listitem> + + <listitem> + <para> + <command>mm_data.mm_message.mm_msg_mime</command> is + the subpart + of the message part. + </para> + </listitem> + </itemizedlist> + </sect3> + + <sect3> + <title>constructor and destructor</title> + + <para> + <command>mailmime_new()</command> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </para> + + <para> + <command>mailmime_free()</command> frees + memory used by + the structure and substructures will also be released. + </para> + + <example> + <title>Creation and display of MIME part</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +/* build one single MIME part */ + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + struct mailmime_data * body; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + /* look at the example in mailmime_content to see how to + build a mailmime_content */ + content_type = build_mime_content(); + + body = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + "foo", 3, NULL); + + mime = mailmime_new(MAILMIME_SINGLE, + NULL, 0, fields, mime_fields, content_type, + body, NULL, NULL, NULL, NULL, NULL); + + /* do the things */ + + mailmime_free(mime); +} + +/* build one single MIME part */ + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + char * str; + struct mailmime_data * body; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + /* look at the example in mailmime_content to see how to + build a mailmime_content */ + content_type = build_mime_content(); + + str = malloc(4); + strcpy(str, "foo"); + + body = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + str, 3, NULL); + + mime = mailmime_new(MAILMIME_SINGLE, + NULL, 0, fields, mime_fields, content_type, + body, NULL, NULL, NULL, NULL, NULL); + + /* do the things */ + + mailmime_free(mime); + free(str); +} + +/* build a MIME part with a sub-message */ + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + char * str; + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, + composite_type); + content_type = mailmime_content_new(type, strdup("rfc2822"), NULL); + + /* build_mime_message() is a function that will build a mime message part */ + sub_mime = build_mime_message(); + + mime = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, fields, mime_fields, content_type, + NULL, NULL, NULL, NULL, sub_mime, NULL); + + /* do the things */ + + mailmime_free(mime); +} + +/* build a MIME part with a sub-message (given by a string) */ + + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + char * str; + struct mailmime_data * msg_content; + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, + composite_type); + content_type = mailmime_content_new(type, strdup("rfc2822"), NULL); + + str = malloc(sizeof(SUB_MESSAGE)); + strcpy(str, SUB_MESSAGE); + + msg_content = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + str, sizeof(SUB_MESSAGE), NULL); + + mime = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, fields, mime_fields, content_type, + NULL, NULL, NULL, NULL, NULL, msg_content); + + /* do the things */ + + mailmime_free(mime); + free(str); +} + +/* build a multipart message */ + + + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + struct mailmime_data * body; + struct mailmime_data * preamble; + struct mailmime_data * epilogue; + clist * list; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, + composite_type); + content_type = mailmime_content_new(type, strdup("mixed"), NULL); + + list = clist_new(); + /* build_mime_message() is a function that will build a mime message part */ + sub_mime = build_mime_message(); + clist_append(list, sub_mime); + sub_mime = build_mime_message(); + clist_append(list, sub_mime); + + preamble = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + PREAMBLE, sizeof(PREAMBLE), NULL); + + epilogue = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + EPILOGUE, sizeof(EPILOGUE), NULL); + + mime = mailmime_new(MAILMIME_SINGLE, + NULL, 0, fields, mime_fields, content_type, + NULL, preamble, epilogue, list, NULL, NULL); + + /* do the things */ + + mailmime_free(mime); +} + +/* display mime part info */ + +void display_mime(struct mailmime * mime) +{ + clistiter * cur; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + printf("single part\n"); + break; + case MAILMIME_MULTIPLE: + printf("multipart\n"); + break; + case MAILMIME_MESSAGE: + printf("message\n"); + break; + } + + printf("part : %p, length : %i\n", + mime->mm_mime_start, mime->mm_length); + printf("\n"); + + if (mime->mm_mime_fields != NULL) { + printf("MIME headers :\n"); + display_mime_fields(mime->mm_mime_fields); + printf("\n"); + } + + printf("content type :\n"); + display_content(mime->mm_content_type); + printf("\n"); + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + display_mime_data(mime->mm_data.mm_single); + break; + + case MAILMIME_MULTIPLE: + if (mime->mm_data.mm_multipart.mm_preamble) { + printf("preamble :\n"); + display_mime_data(mime->mm_data.mm_multipart.mm_preamble); + printf("\n"); + } + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + display_mime(clist_content(cur)); + } + + if (mime->mm_data.mm_multipart.mm_epilogue) { + printf("epilogue :\n"); + display_mime_data(mime->mm_data.mm_multipart.mm_epilogue); + printf("\n"); + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_fields) { + printf("headers :\n"); + display_field(mime->mm_data.mm_message.mm_msg_fields); + printf("\n"); + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + printf("sub message %p :\n", + mime->mm_data.mm_message.mm_msg_mime); + display_mime(mime->mm_data.mm_message.mm_msg_mime); + printf("end of sub message %p\n", + mime->mm_data.mm_message.mm_msg_mime); + } + break; + } +} + </programlisting> + </example> + + </sect3> + + </sect2> + + <!-- mailmime_disposition --> + <sect2 id="mailmime-disposition"> + <title>mailmime_disposition - MIME disposition information (Content-Disposition)</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailmime_disposition { + struct mailmime_disposition_type * dsp_type; + clist * dsp_parms; /* struct mailmime_disposition_parm */ +}; + </programlisting> + + <para> + This is the parsed <command>Content-Disposition</command> + header field. + </para> + + <itemizedlist> + <listitem> + <para> + <command>dsp_type</command> is the type of disposition + (see <xref linkend="mailmime-disposition-type">). + </para> + </listitem> + + <listitem> + <para> + <command>dsp_parms</command> is the list of parameters + of <command>Content-Disposition</command> header field. + Each element is of type <command>mailmime_disposition_parm</command> + (see <xref linkend="mailmime-disposition-parm">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>Creation and display of MIME disposition information</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_disposition * disposition; + struct mailmime_disposition_type * disposition_type; + clist * disposition_parms; + struct mailmime_disposition_parm * param; + + disposition_type = + mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, NULL); + + disposition_parms = clist_new(); + param = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME, + strdup("foo.txt"), NULL, + NULL, NULL, -1, NULL); + clist_append(disposition_parms, param); + + disposition = mailmime_disposition_new(disposition_type, disposition_parms); + + /* do the things */ + + mailmime_disposition_free(disposition); +} + +void display_mime_disposition(struct mailmime_disposition * disposition) +{ + clistiter * cur; + + printf("disposition type:\n"); + display_mailmime_disposition_type(disposition->dsp_type); + printf("\n"); + printf("disposition parameters:\n"); + for(cur = clist_begin(disposition->dsp_parms) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parm * param; + + param = clist_content(cur); + display_mime_disposition_parm(param); + } + printf("\n"); +} + + </programlisting> + </example> + </sect2> + + <!-- mailmime_disposition_type --> + <sect2 id="mailmime-disposition-type"> + <title>mailmime_disposition_type - Type of MIME disposition</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition_type { + int dsp_type; + char * dsp_extension; +}; + </programlisting> + + <para> + This is the type of MIME disposition. + Parsed <command>Content-Disposition</command> field without + parameters. + </para> + + <para> + <command>dsp_type</command> is the type of disposition. + The value can be + <command>MAILMIME_DISPOSITION_TYPE_INLINE</command> + if MIME disposition is inline, + <command>MAILMIME_DISPOSITION_TYPE_ATTACHMENT</command> + if MIME disposition is attachment, + <command>MAILMIME_DISPOSITION_TYPE_EXTENSION</command> + for other. In this case, <command>dsp_extension</command> must be + set. + <command>MAILMIME_DISPOSITION_TYPE_ERROR</command> is used internally. + </para> + + <example> + <title>Creation and display of MIME disposition type</title> + <programlisting role="C"> +#include <libetpan/libetpan.h> + +/* standard disposition type */ + +int main(int argc, char ** argv) +{ + struct mailmime_disposition_type * disposition_type; + + disposition_type = + mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, NULL); + + /* do the things */ + + mailmime_disposition_type_free(disposition_type); +} + +/* disposition type extension */ + +int main(int argc, char ** argv) +{ + struct mailmime_disposition_type * disposition_type; + + disposition_type = + mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_EXTENSION, + strdup("mydisposition")); + + /* do the things */ + + mailmime_disposition_type_free(disposition_type); +} + +void display_mime_disposition_type(struct mailmime_disposition_type * disposition_type) +{ + switch (disposition->dsp_type) { + case MAILMIME_DISPOSITION_TYPE_INLINE: + printf("inline\n"); + break; + case MAILMIME_DISPOSITION_TYPE_ATTACHMENT: + printf("attachment\n"); + break; + case MAILMIME_DISPOSITION_TYPE_EXTENSION: + printf("extension : %s\n", disposition_type->dsp_extension); + break; + } +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_disposition_parm --> + <sect2 id="mailmime-disposition-parm"> + <title>mailmime_disposition_parm - MIME disposition parameter</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISPOSITION_PARM_FILENAME, + MAILMIME_DISPOSITION_PARM_CREATION_DATE, + MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, + MAILMIME_DISPOSITION_PARM_READ_DATE, + MAILMIME_DISPOSITION_PARM_SIZE, + MAILMIME_DISPOSITION_PARM_PARAMETER +}; + +struct mailmime_disposition_parm { + int pa_type; + union { + char * pa_filename; + char * pa_creation_date; + char * pa_modification_date; + char * pa_read_date; + size_t pa_size; + struct mailmime_parameter * pa_parameter; + } pa_data; +}; + </programlisting> + + <para> + This is a parameter of MIME disposition information. For + example, this can be + <command>filename="foo.jpg"</command>. + </para> + + <itemizedlist> + <listitem> + <para> + <command>pa_type</command> is the type of + disposition. The value can be + <command>MAILMIME_DISPOSITION_PARM_FILENAME</command> + for a filename parameter, + <command>MAILMIME_DISPOSITION_PARM_CREATION_DATE</command> + for a creation date parameter, + <command>MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE</command> + for a modification date parameter, + <command>MAILMIME_DISPOSITION_PARM_READ_DATE</command> + for a last read date parameter, + <command>MAILMIME_DISPOSITION_PARM_SIZE</command> + for a file size parameter or + <command>MAILMIME_DISPOSITION_PARM_PARAMETER</command> + for other parameters. + </para> + </listitem> + + <listitem> + <para> + <command>pa_data.pa_filename</command> is the filename + parameter when <command>pa_type</command> is + <command>MAILMIME_DISPOSITION_PARM_FILENAME</command> + This is a string containing the name of the + file. + </para> + </listitem> + <listitem> + <para> + <command>pa_data.pa_creation_date</command> is the + creation date parameter when <command>pa_type</command> is + <command>MAILMIME_DISPOSITION_PARM_CREATION_DATE</command>. + This is a string containing the formatted creation date. + </para> + </listitem> + + <listitem> + <para> + <command>pa_data.pa_modification_date</command> is the + modification date parameter when <command>pa_type</command> is + <command>MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE</command>. + This is a string containing the formatted modification date. + </para> + </listitem> + + <listitem> + <para> + <command>pa_data.pa_read_date</command> is the + last read date parameter when <command>pa_type</command> is + <command>MAILMIME_DISPOSITION_PARM_READ_DATE</command>. + This is a string containing the formatted last read date. + </para> + </listitem> + + <listitem> + <para> + <command>pa_data.pa_size</command> is the size + parameter when <command>pa_type</command> is + <command>MAILMIME_DISPOSITION_PARM_SIZE</command>. + This gives the size of the file. + </para> + </listitem> + + <listitem> + <para> + <command>pa_data.pa_parameter</command> is the + name and the value of the parameter when + <command>pa_type</command> is + <command>MAILMIME_DISPOSITION_PARM_PARAMETER</command> + (see <xref linkend="mailmime-parameter">) + </para> + </listitem> + </itemizedlist> + + <example> + <title>Creation and display of MIME disposition + parameter</title> + + <programlisting role="C"> +int main(int argc, char ** argv) +{ + struct mailmime_disposition_parm * param; + + disposition_parms = clist_new(); + param = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME, + strdup("foo.txt"), NULL, + NULL, NULL, -1, NULL); + /* do the things */ + + mailmime_disposition_parm_free(param); +} + +void display_mime_dsp_parm(struct mailmime_disposition_parm * param) +{ + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + printf("filename: %s\n", param->pa_data.pa_filename); + break; + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + printf("creation date: %s\n", param->pa_data.pa_creation_date); + break; + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + printf("modification date: %s\n", param->pa_data.pa_modification_date); + break; + case MAILMIME_DISPOSITION_PARM_READ_DATE: + printf("read date: %s\n", param->pa_data.pa_read_date); + break; + case MAILMIME_DISPOSITION_PARM_SIZE: + printf("size: %lu\n", (unsigned long) param->pa_data.pa_size); + break; + case MAILMIME_DISPOSITION_PARM_PARAMETER: + printf("MIME disposition param:\n"); + display_mime_parameter(param->pa_data.pa_parameter); + break; + } +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_single_fields --> + <sect2 id="mailmime-single-fields"> + <title>mailmime_single_fields - MIME headers</title> + + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailmime_single_fields { + struct mailmime_content * fld_content; + char * fld_content_charset; + char * fld_content_boundary; + char * fld_content_name; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + char * fld_disposition_filename; + char * fld_disposition_creation_date; + char * fld_disposition_modification_date; + char * fld_disposition_read_date; + size_t fld_disposition_size; + struct mailmime_language * fld_language; +}; + +struct mailmime_single_fields * +mailmime_single_fields_new(struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +void mailmime_single_fields_free(struct mailmime_single_fields * + single_fields); + +void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, + struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + </programlisting> + + <para> + <command>mailmime_fields</command> (see <xref + linkend="mailmime-fields">) is the native structure + that MIME module will use, this module will provide an easier + structure to use when + parsing fields. <command>mailmime_single_fields</command> is + an easier structure to get parsed fields, rather than + iteration over the list of fields. + </para> + + <itemizedlist> + <listitem> + <para> + <command>fld_content</command> is the MIME content type + (see <xref linkend="mailmime-content">). + </para> + </listitem> + <listitem> + <para> + <command>fld_content_charset</command> is the value + of the MIME type parameter <command>charset</command>. + </para> + </listitem> + <listitem> + <para> + <command>fld_content_boundary</command> is the value + of the MIME type parameter <command>boundary</command>. + </para> + </listitem> + <listitem> + <para> + <command>fld_content_name</command> is the value + of the MIME type parameter <command>name</command>. + </para> + </listitem> + <listitem> + <para> + <command>fld_encoding</command> is the MIME encoding + mechanism used + (see <xref linkend="mailmime-mechanism">). + </para> + </listitem> + <listitem> + <para> + <command>fld_id</command> is the content of the field + <command>Content-ID</command>. + </para> + </listitem> + <listitem> + <para> + <command>fld_description</command> is the content of the field + <command>Content-Description</command>. + </para> + </listitem> + <listitem> + <para> + <command>fld_version</command> is the version of MIME + in use. + </para> + </listitem> + <listitem> + <para> + <command>fld_disposition</command> is the MIME + disposition information + (see <xref linkend="mailmime-disposition">). + </para> + </listitem> + <listitem> + <para> + <command>fld_disposition_filename</command> is + the <command>filename</command> parameter of the + MIME disposition information. + </para> + </listitem> + <listitem> + <para> + <command>fld_disposition_creation_date</command> is + the <command>creation-date</command> parameter of the + MIME disposition information. + </para> + </listitem> + <listitem> + <para> + <command>fld_disposition_modification_date</command> is + the <command>modification-date</command> parameter of the + MIME disposition information. + </para> + </listitem> + <listitem> + <para> + <command>fld_disposition_read_date</command> is + the <command>read-date</command> parameter of the + MIME disposition information. + </para> + </listitem> + <listitem> + <para> + <command>fld_disposition_size</command> is + the <command>size</command> parameter of the + MIME disposition information. + </para> + </listitem> + <listitem> + <para> + <command>fld_language</command> is the language + of the MIME part + (see <xref linkend="mailmime-language">). + </para> + </listitem> + <listitem> + <para> + <command>single_fields</command> is the structure to fill. + </para> + </listitem> + <listitem> + <para> + <command>fld_fields</command> is the MIME fields list to + use to fill the <command>single_fields</command>. + </para> + </listitem> + </itemizedlist> + + <para> + <command>mailmime_single_fields_new()</command> creates and + initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will <emphasis>NOT</emphasis> be freed if the + object is released. + </para> + + <para> + <command>mailmime_single_fields_free()</command> frees + memory used by the structure and + substructures will <emphasis>NOT</emphasis> be + released. They should be released by + the application. + </para> + + <para> + <command>mailimf_single_fields_init()</command> will + initialize fill the data structure, using + the given argument (<command>fld_fields</command> and + <command>fld_content</command>). The interesting fields will + be filled into single_fields. + </para> + + <example> + <title>Creation and display of single fields</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_single_fields * single_fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + /* look at the example in mailmime_content to see how to + build a mailmime_content */ + content_type = build_mime_content(); + + single_fields = mailmime_single_fields_new(mime_fields, content_type); + + /* do the things */ + + mailmime_single_fields_free(single_fields); + mailmime_fields_free(mime_fields); +} + +void display_mime_single_fields(struct mailmime_single_fields * single_fields) +{ + if (single_fields->fld_content != NULL) { + printf("content type:\n"); + display_mime_content(single_fields->fld_content); + printf("\n"); + } + if (single_fields->fld_content_charset != NULL) { + printf("content type charset: %s\n", + single_fields->fld_content_charset); + printf("\n"); + } + if (single_fields->fld_content_boundary != NULL) { + printf("content type boundary: %s\n", + single_fields->fld_content_boundary); + printf("\n"); + } + if (single_fields->content_name != NULL) { + printf("content type name: %s\n", single_fields->content_name); + printf("\n"); + } + if (single_fields->fld_encoding != NULL) { + printf("content transfer encoding:\n"); + display_mime_mechanism(single_fields->fld_encoding); + printf("\n"); + } + if (single_fields->fld_id != NULL) { + printf("content id: %s\n", single_fields->fld_id); + printf("\n"); + } + if (single_fields->fld_description != NULL) { + printf("content description: %s\n", single_fields->fld_description); + printf("\n"); + } + if (single_fields->fld_version != 0) { + printf("mime version: %i.%i\n", + single_fields->fld_version>> 16, + single_fields->fld_version & 0xFFFF); + printf("\n"); + } + if (single_fields->fld_disposition != NULL) { + printf("content disposition:\n"); + display_mime_disposition(single_fields->fld_disposition); + printf("\n"); + } + if (single_fields->fld_disposition_filename != NULL) { + printf("content disposition filename: %s\n", + single_fields->fld_disposition_filename); + printf("\n"); + } + if (single_fields->fld_disposition_creation_date != NULL) { + printf("content disposition creation date: %s\n", + single_fields->fld_disposition_creation_date); + printf("\n"); + } + if (single_fields->fld_disposition_modification_date != NULL) { + printf("content disposition modification date: %s\n", + single_fields->fld_disposition_modification_date); + printf("\n"); + } + if (single_fields->fld_disposition_read_date != NULL) { + printf("content disposition read date: %s\n", + single_fields->fld_disposition_read_date; + printf("\n"); + } + if (single_fields->fld_disposition_size != (size_t) -1) { + printf("content disposition size : %i\n", + single_fields->fld_disposition_size); + printf("\n"); + } + if (single_fields->language != NULL) { + printf("content language:\n"); + display_mime_language(single_fields->fld_language); + printf("\n"); + } +} + </programlisting> + </example> + </sect2> + + </sect1> + + <!-- Parser functions --> + <sect1> + <title>Parser functions</title> + + <!-- mailmime_content_parse --> + <sect2 id="mailmime-content-parse"> + <title>mailmime_content_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_content_parse(const char * message, size_t length, + size_t * index, + struct mailmime_content ** result); + </programlisting> + + <para> + This function will parse the content of a + <command>Content-Type</command> header field. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> is a string containing + the MIME content type. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> is a pointer to the start of + the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command> + (see <xref linkend="mailmime-content">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>Parsing MIME content type</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Type") == 0) { + struct mailmime_content * content_type; + size_t current_index; + + current_index = 0; + r = mailmime_content_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &content_type); + if (r == MAILIMF_NO_ERROR) { + display_mime_content(content_type); + /* do the things */ + status = EXIT_SUCCESS; + mailmime_content_free(content_type); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_description_parse --> + <sect2 id="mailmime-description-parse"> + <title>mailmime_description_parse</title> + + <programlisting role="C"> +#include >libetpan/libetpan.h< + +int mailmime_description_parse(const char * message, size_t length, + size_t * index, + char ** result); + </programlisting> + + <para> + This will parse the content of + <command>Content-Description</command> MIME header field. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> is a string containing + the MIME content description. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> is a pointer to the start of + the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command>. + The result string must be freed with + <command>free()</command>. + </para> + </listitem> + </itemizedlist> + + <example> + <title>Parsing MIME description</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Description") == 0) { + char * description; + size_t current_index; + + current_index = 0; + r = mailmime_description_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &description); + if (r == MAILIMF_NO_ERROR) { + printf("%s\n", description); + /* do the things */ + status = EXIT_SUCCESS; + free(description); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + + + </sect2> + + <!-- mailmime_encoding_parse --> + <sect2 id="mailmime-encoding-parse"> + <title>mailmime_encoding_parse</title> + + <programlisting role="C"> +#include >libetpan/libetpan.h< + +int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result); + </programlisting> + + <para> + This function will parse the content of + <command>Content-Transfer-Encoding</command> header field. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> is a string containing + the MIME encoding mechanism. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> is a pointer to the start of + the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command> + (see <xref linkend="mailmime-mechanism">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>parsing MIME encoding mechanism</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Transfer-Encoding") == 0) { + struct mailmime_content * encoding; + size_t current_index; + + current_index = 0; + r = mailmime_encoding_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &encoding); + if (r == MAILIMF_NO_ERROR) { + display_mime_mechanism(encoding); + /* do the things */ + status = EXIT_SUCCESS; + mailmime_mechanism_free(encoding); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_field_parse --> + <sect2 id="mailmime-field-parse"> + <title>mailmime_field_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int +mailmime_field_parse(struct mailimf_optional_field * field, + struct mailmime_field ** result); + </programlisting> + + <para> + This function will parse a MIME header field. + </para> + + <itemizedlist> + <listitem> + <para> + <command>field</command> is a non-parsed field + (see <xref linkend="mailimf-optional-field">). + </para> + + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command> + (see <xref linkend="mailmime-field">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>parsing MIME header field</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + r = mailmime_field_parse(field->fld_data.fld_optional_field, + &mime_fields); + if (r == MAILIMF_NO_ERROR) { + display_mime_field(mime_field); + mailmime_field_free(mime_field); + status = EXIT_SUCCESS; + } + } + } + + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + + </sect2> + + <!-- mailmime_id_parse --> + <sect2 id="mailmime-id-parse"> + <title>mailmime_id_parse</title> + + <programlisting role="C"> +#include >libetpan/libetpan.h< + +int mailmime_id_parse(const char * message, size_t length, + size_t * index, char ** result); + </programlisting> + + <para> + This will parse the content of + <command>Content-ID</command> MIME header field. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> is a string containing + the MIME content identifier. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> is a pointer to the start of + the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command>. + The result string must be freed with + <command>free()</command>. + </para> + </listitem> + </itemizedlist> + + <example> + <title>Parsing MIME content identifier</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-ID") == 0) { + char * id; + size_t current_index; + + current_index = 0; + r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &id); + if (r == MAILIMF_NO_ERROR) { + printf("%s\n", id); + /* do the things */ + status = EXIT_SUCCESS; + free(id); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_fields_parse --> + <sect2 id="mailmime-fields-parse"> + <title>mailmime_fields_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int +mailmime_fields_parse(struct mailimf_fields * fields, + struct mailmime_fields ** result); + </programlisting> + + <para> + This function will parse a MIME header fields. + </para> + + <itemizedlist> + <listitem> + <para> + <command>fields</command> is a list of RFC 2822 fields + (see <xref linkend="mailimf-fields">). + </para> + + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command> + (see <xref linkend="mailmime-fields">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>parsing MIME header fields</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + struct mailmime_fields * mime_fields; + + r = mailmime_fields_parse(f, &mime_fields); + if (r == MAILIMF_NO_ERROR) { + display_mime_fields(mime_fields); + mailmime_fields_free(mime_fields); + status = EXIT_SUCCESS; + } + + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + + </sect2> + + <!-- mailmime_version_parse --> + <sect2 id="mailmime-version-parse"> + <title>mailmime_version_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_version_parse(const char * message, size_t length, + size_t * index, + uint32_t * result); + </programlisting> + + <para> + This will parse the content of + <command>MIME-Version</command> MIME header field. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> is a string containing + the MIME version. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> is a pointer to the start of + the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command> + (see <xref linkend="mailmime-field">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>parsing MIME version</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "MIME-Version") == 0) { + uint32_t version; + size_t current_index; + + current_index = 0; + r = mailmime_version_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &version); + if (r == MAILIMF_NO_ERROR) { + printf("%i.%i\n", version >> 16, version & 0xFFFF); + /* do the things */ + status = EXIT_SUCCESS; + free(description); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_parameter_parse --> + <sect2 id="mailmime-parameter-parse"> + <title>mailmime_parameter_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_parameter_parse(const char * message, size_t length, + size_t * index, + struct mailmime_parameter ** result); + </programlisting> + + <para> + This will parse a MIME parameter (parameter of + <command>Content-Type</command> or parameter of + <command>Content-Disposition</command>). + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> is a string containing + the MIME parameter. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> is a pointer to the start of + the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command> + (see <xref linkend="mailmime-parameter">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>parsing a MIME parameter</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +#define PARAM_STR "foo=bar" + +int main(int argc, char ** argv) +{ + int fd; + int r; + size_t current_index; + struct mailmime_parameter * param; + int status; + + status = EXIT_FAILURE; + + current_index = 0; + r = mailmime_parameter_parse(PARAM_STR, sizeof(PARAM_STR) - 1, + ¤t_index, ¶m); + if (r == MAILIMF_NO_ERROR) { + display_mime_parameter(param); + /* do the things */ + mailmime_parameter_free(param); + status = EXIT_SUCCESS; + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_language_parse --> + <sect2 id="mailmime-language-parse"> + <title>mailmime_language_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_language_parse(const char * message, size_t length, + size_t * index, + struct mailmime_language ** result); + </programlisting> + + <para> + This function will parse the content of a + <command>Content-Language</command> header. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> is a string containing + the MIME content language. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> is a pointer to the start of + the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command> + (see <xref linkend="mailmime-language">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>Parsing the MIME content langage</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Language") == 0) { + struct mailmime_language * lang; + size_t current_index; + + current_index = 0; + r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &lang); + if (r == MAILIMF_NO_ERROR) { + display_mime_language(lang); + /* do the things */ + status = EXIT_SUCCESS; + free(id); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_disposition_parse --> + <sect2 id="mailmime-disposition-parse"> + <title>mailmime_disposition_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_disposition_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition ** result); + </programlisting> + + <para> + This function will parse the content of a + <command>Content-Disposition</command> MIME header field. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> is a string containing + the MIME content disposition. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> is a pointer to the start of + the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command> + (see <xref linkend="mailmime-disposition">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>Parsing the MIME content disposition</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Disposition") == 0) { + struct mailmime_disposition * dsp; + size_t current_index; + + current_index = 0; + r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &dsp); + if (r == MAILIMF_NO_ERROR) { + display_mime_disposition(dsp); + /* do the things */ + status = EXIT_SUCCESS; + free(id); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_disposition_type_parse --> + <sect2 id="mailmime-disposition-type-parse"> + <title>mailmime_disposition_type_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int +mailmime_disposition_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_type ** + result); + </programlisting> + + <para> + This function will parse the type of MIME content + disposition. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> is a string containing + the MIME content disposition type. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> is a pointer to the start of + the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command> + (see <xref linkend="mailmime-disposition-type">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>parsing a MIME content disposition type</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +#define DSP_TYPE_STR "attachment" + +int main(int argc, char ** argv) +{ + int fd; + int r; + size_t current_index; + struct mailmime_disposition_type * dsp_type; + int status; + + status = EXIT_FAILURE; + + current_index = 0; + r = mailmime_disposition_type_parse(DSP_TYPE_STR, sizeof(DSP_TYPE_STR) - 1, + ¤t_index, &dsp_type); + if (r == MAILIMF_NO_ERROR) { + display_mime_disposition_type(dsp_type); + /* do the things */ + mailmime_disposition_type_free(dsp_type); + status = EXIT_SUCCESS; + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_encoded_phrase_parse --> + <sect2 id="mailmime-encoded-phrase-parse"> + <title>mailmime_encoded_phrase_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_encoded_phrase_parse(const char * default_fromcode, + const char * message, size_t length, + size_t * index, const char * tocode, + char ** result); + </programlisting> + + <para> + This function will decode a MIME encoded header string, + encoded with RFC 2047. + </para> + + <itemizedlist> + <listitem> + <para> + <command>default_fromcode</command> is the default + code to use for parts of string that are not marked + with charset. + </para> + </listitem> + <listitem> + <para> + <command>message</command> is the string to decode. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> is a pointer to the start of + the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>tocode</command> is the destination charset + for decoding. + </para> + </listitem> + <listitem> + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command>. + </para> + </listitem> + </itemizedlist> + + <example> + <title>decoding a MIME encoded header string</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +#define TEST_STRING "=?iso-8859-1?ab?= =?iso-8859-15?cd?=" + +int main(int argc, char ** argv) +{ + size_t cur_token; + char * decoded_subject; + + cur_token = 0; + mailmime_encoded_phrase_parse("iso-8859-1", + TEST_STRING, sizeof(TEST_STRING), + &cur_token, "iso-8859-1", &decoded_subject); + + printf("%s\n", decoded_subject); + + /* do the things */ + + free(decoded_subject); +} + </programlisting> + </example> + + </sect2> + + <!-- mailmime_parse --> + <sect2 id="mailmime-parse"> + <title>mailmime_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_parse(const char * message, size_t length, + size_t * index, struct mailmime ** result); + </programlisting> + + <para> + This will parse a MIME message. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> is a string containing + the MIME message. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> is a pointer to the start of + the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command> + (see <xref linkend="mailmime">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>parsing a MIME message</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailmime * mime; + size_t current_index; + + current_index = 0; + r = mailmime_parse(mem, stat_info.st_size, + ¤t_index, &mime); + if (r == MAILIMF_NO_ERROR) { + display_mime(mime); + /* do the things */ + status = EXIT_SUCCESS; + mailmime_free(mime); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_base64_body_parse --> + <sect2 id="mailmime-base64-body-parse"> + <title>mailmime_base64_body_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_base64_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + </programlisting> + + <para> + This function will parse a body part encoded using base64. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> is a string encoded using + base64. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> is a pointer to the start of + the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command> + The result must be freed with + <command>mmap_string_unref()</command>. + </para> + </listitem> + </itemizedlist> + + <example> + <title>Parsing a base64 encoded part</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_base64_body_parse(mem, stat_info.st_size, + ¤t_index, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_quoted_printable_body_parse --> + <sect2 id="mailmime-quoted-printable-body-parse"> + <title>mailmime_quoted_printable_body_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_quoted_printable_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len, int in_header); + </programlisting> + + <para> + This function will parse a body part encoded using quoted + printable. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> is a string encoded using + quoted printable. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> is a pointer to the start of + the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command> + The result must be freed with + <command>mmap_string_unref()</command>. + </para> + </listitem> + </itemizedlist> + + <example> + <title>Parsing a quoted printable encoded part</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_quoted_printable_body_parse(mem, stat_info.st_size, + ¤t_index, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_binary_body_parse --> + <sect2 id="mailmime-binary-body-parse"> + <title>mailmime_binary_body_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_binary_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + </programlisting> + + <para> + This function will parse a body part encoded using binary + (no encoding). + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> is a string encoded using + binary. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> is a pointer to the start of + the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command> + The result must be freed with + <command>mmap_string_unref()</command>. + </para> + </listitem> + </itemizedlist> + + <example> + <title>Parsing a binary encoded part</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_binary_body_parse(mem, stat_info.st_size, + ¤t_index, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_part_parse --> + <sect2 id="mailmime-part-parse"> + <title>mailmime_part_parse</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +int mailmime_part_parse(const char * message, size_t length, + size_t * index, + int encoding, char ** result, size_t * result_len); + </programlisting> + + <para> + This function will parse a body part encoded using a + given MIME encoding mechanism. + </para> + + <itemizedlist> + <listitem> + <para> + <command>message</command> is a string encoded using + binary. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the size of the given + string. + </para> + </listitem> + <listitem> + <para> + <command>index</command> is a pointer to the start of + the address in the given string, <command>(* + index)</command> is modified to point at the end of the + parsed data. + </para> + </listitem> + <listitem> + <para> + <command>encoding</command> is a MIME encoding + mechanism. The value can be + <command>MAILMIME_MECHANISM_7BIT</command>, + <command>MAILMIME_MECHANISM_8BIT</command>, + <command>MAILMIME_MECHANISM_BINARY</command>, + <command>MAILMIME_MECHANISM_QUOTED_PRINTABLE</command>, + <command>MAILMIME_MECHANISM_BASE64</command> or + <command>MAILMIME_MECHANISM_TOKEN</command> + (see <xref linkend="mailmime-mechanism">). + </para> + </listitem> + <listitem> + <para> + <command>result</command>. The result of the parse + operation is stored in <command>(* result)</command> + The result must be freed with + <command>mmap_string_unref()</command>. + </para> + </listitem> + </itemizedlist> + + <example> + <title>Parsing a MIME encoded part</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_part_parse(mem, stat_info.st_size, ¤t_index, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + + </sect1> + + <sect1> + <title>Rendering of MIME parts</title> + + <!-- mailmime_fields_write --> + <sect2 id="mailmime-fields-write"> + <title>mailmime_fields_write, mailmime_content_write and + mailmime_content_type_write</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields); + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content); + </programlisting> + + <para> + <command>mailmime_fields_write</command> render the MIME + header fields. + </para> + + <para> + <command>mailmime_content_write</command> render the MIME + content type header field. + </para> + + <para> + <command>mailmime_content_write</command> render the + content of the MIME content type header field. + </para> + + <itemizedlist> + <listitem> + <para> + <command>col</command> current column is given for wrapping + purpose in <command>(* col)</command>, + the resulting columns will be returned.. + </para> + </listitem> + <listitem> + <para> + <command>f</command> is the file descriptor. It can be + stdout for example. + </para> + </listitem> + <listitem> + <para> + <command>fields</command> is the header fields + (see <xref linkend="mailmime-fields">). + </para> + </listitem> + <listitem> + <para> + <command>content</command> is the header fields + (see <xref linkend="mailmime-content">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>rendering MIME header fields</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_mime * mime_fields; + int col; + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + col = 0; + mailmime_fields_write(stdout, &col, mime_fields); + + mailmime_fields_free(mime_fields); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + int col; + + /* look at the example in mailmime_content to see how to + build a mailmime_fields */ + content = build_mime_content(); + + col = 0; + mailmime_content_write(stdout, &col, mime_fields); + + mailmime_content_free(content); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + int col; + + /* look at the example in mailmime_content to see how to + build a mailmime_fields */ + content = build_mime_content(); + + col = 0; + mailmime_content_type_write(stdout, &col, mime_fields); + + mailmime_content_free(content); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_write --> + <sect2 id="mailmime-write"> + <title>mailmime_write</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info); + </programlisting> + + <para> + This function will render a MIME message. + </para> + + <itemizedlist> + <listitem> + <para> + <command>col</command> current column is given for wrapping + purpose in <command>(* col)</command>, + the resulting columns will be returned.. + </para> + </listitem> + <listitem> + <para> + <command>f</command> is the file descriptor. It can be + stdout for example. + </para> + </listitem> + <listitem> + <para> + <command>build_info</command> is the MIME message to + render. + </para> + </listitem> + </itemizedlist> + + </sect2> + + <!-- mailmime_quoted_printable_write --> + <sect2 id="mailmime-quoted-printable-write"> + <title>mailmime_quoted_printable_write + and mailmime_base64_write</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size); + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size); + </programlisting> + + <para> + <command>mailmime_quoted_printable_write()</command> will + render a string to quoted printable. + </para> + + <para> + <command>mailmime_base64_write()</command> will + render a string to base64. + </para> + + <itemizedlist> + <listitem> + <para> + <command>col</command> current column is given for wrapping + purpose in <command>(* col)</command>, + the resulting columns will be returned.. + </para> + </listitem> + <listitem> + <para> + <command>f</command> is the file descriptor. It can be + stdout for example. + </para> + </listitem> + <listitem> + <para> + <command>text</command> is the string to render. + </para> + </listitem> + <listitem> + <para> + <command>size</command> is the size of the string to + render. + </para> + </listitem> + </itemizedlist> + + <example> + <title>render base64 or quoted printable</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + int col; + + col = 0; + mailmime_quoted_printable_write(stdout, &col, + "this is a test", 14); +} + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + int col; + + col = 0; + mailmime_base64_write(stdout, &col, "this is a test", 14); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_data_write --> + <sect2 id="mailmime-data-write"> + <title>mailmime_data_write</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext); + </programlisting> + + <para> + <command>mailmime_data_write</command> will + render MIME data. + </para> + + <itemizedlist> + <listitem> + <para> + <command>col</command> current column is given for wrapping + purpose in <command>(* col)</command>, + the resulting columns will be returned.. + </para> + </listitem> + <listitem> + <para> + <command>f</command> is the file descriptor. It can be + stdout for example. + </para> + </listitem> + <listitem> + <para> + <command>data</command> is the data to render + (see <xref linkend="mailmime-data">). + </para> + </listitem> + </itemizedlist> + </sect2> + </sect1> + + <!-- Creation functions --> + <sect1> + <title>Creation functions</title> + + <!-- mailmime_disposition_new_filename --> + <sect2 id="mailmime-disposition-new-filename"> + <title>mailmime_disposition_new_filename and + mailmime_disposition_new_with_data</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition * +mailmime_disposition_new_filename(int type, char * filename); + +struct mailmime_disposition * +mailmime_disposition_new_with_data(int type, + char * filename, char * creation_date, char * modification_date, + char * read_date, size_t size); + </programlisting> + + <para> + These functions will create a MIME content disposition + information. + </para> + + <itemizedlist> + <listitem> + <para> + <command>type</command> a standard MIME disposition : + <command>MAILMIME_DISPOSITION_TYPE_INLINE</command> or + <command>MAILMIME_DISPOSITION_TYPE_ATTACHMENT</command>. + </para> + <para> + <command>filename</command> is the filename. + </para> + <para> + <command>creation_date</command> is the creation date. + </para> + <para> + <command>modification_date</command> is the modification + date. + </para> + <para> + <command>read_date</command> is the last read date. + </para> + <para> + <command>size</command> is the size of the file. + </para> + </listitem> + <listitem> + <para> + This will return a MIME content disposition + (see <xref linkend="mailmime-disposition">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>creating a MIME content disposition</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_disposition * disposition; + + disposition = + mailmime_disposition_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + strdup("foo-bar.txt")); + + /* do the things */ + + mailmime_disposition_free(disposition); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_fields_new_empty --> + <sect2 id="mailmime-fields-new-empty"> + <title>mailmime_fields_new_empty and mailmime_fields_add</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailmime_fields * mailmime_fields_new_empty(void); + +int mailmime_fields_add(struct mailmime_fields * fields, + struct mailmime_field * field); + </programlisting> + + <para> + <command>mailmime_fields_new_empty()</command> will + create a new empty MIME header fields list. + </para> + + <para> + <command>mailmime_fields_add()</command> will add + MIME header fields to the MIME header fields list. + </para> + + <itemizedlist> + <listitem> + <para> + <command>fields</command>. The MIME header field will + be added to this MIME header fields list + (see <xref linkend="mailmime-fields">). + </para> + </listitem> + <listitem> + <para> + <command>field</command> is the MIME header field to add + (see <xref linkend="mailmime-field">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>creating a MIME header fields list</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_fields * fields; + struct mailmime_field * field; + + fields = mailmime_fields_new_empty(); + field = build_mime_field(); + + /* do the things */ + + mailmime_fields_add(fields, field); + + mailmime_fields_free(fields); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_fields_new_with_data --> + <sect2 id="mailmime-fields-new-with-data"> + <title>mailmime_fields_new_with_data and + mailmime_fields_new_with_version</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailmime_fields * +mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +struct mailmime_fields * +mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + </programlisting> + + <para> + <command>mailmime_fields_new_with_data()</command> will + create a MIME header fields list with all the given fields + (<command>NULL</command> can be used for the value if the + field must not be present). + <command>MIME-Version</command> header field will + <emphasis>not</emphasis> be added. + </para> + + <para> + <command>mailmime_fields_new_with_version()</command> will + create a MIME header fields list with all the given fields + (<command>NULL</command> can be used for the value if the + field must not be present). + <command>MIME-Version</command> header field will be added. + </para> + + <example> + <title>creating new fields</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_disposition * disposition; + struct mailmime_fields * mime_fields; + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL); + + disposition = + mailmime_disposition_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + strdup("foo-bar.txt")); + + mime_fields = mailmime_fields_new_with_version(encoding, NULL, + NULL, disposition, NULL); + + /* do the things */ + + mailmime_fields_free(mime_fields); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_get_content_message --> + <sect2 id="mailmime-get-content-message"> + <title>mailmime_get_content_message</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailmime_content * mailmime_get_content_message(void); + +struct mailmime_content * mailmime_get_content_text(void); + +struct mailmime_content * mailmime_content_new_with_str(const char * str); + </programlisting> + + <para> + <command>mailmime_get_content_message()</command> will + create a MIME content type + <command>message/rfc822</command>. + </para> + + <para> + <command>mailmime_get_content_text()</command> will + create a MIME content type + <command>plain/text</command>. + </para> + + <para> + <command>mailmime_get_content_new_with_str()</command> will + create a MIME content type given by the string + <command>plain/text</command>. + </para> + + <para> + <command>str</command>. This string will + <command>NOT</command> be referenced by any structure. + This string will only be parsed to create the structure. + </para> + + <example> + <title>Creating a MIME content type</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + + content = mailmime_get_content_message(); + + /* do the things */ + + mailmime_content_free(content); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + /* do the things */ + + mailmime_content_free(content); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + + content = mailmime_get_content_new_with_str("multipart/mixed"); + + /* do the things */ + + mailmime_content_free(content); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_data_new_data --> + <sect2 id="mailmime-data-new-data"> + <title>mailmime_data_new_data and mailmime_data_new_file</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_data * +mailmime_data_new_data(int encoding, int encoded, + const char * data, size_t length); + +struct mailmime_data * +mailmime_data_new_file(int encoding, int encoded, + char * filename); + </programlisting> + + <para> + <command>mailmime_data_new_data()</command> will create a + new MIME content, using a string in memory. + </para> + + <para> + <command>mailmime_data_new_file()</command> will create a + new MIME content, using a file. + </para> + + <itemizedlist> + <listitem> + <para> + <command>encoding</command> is the MIME encoding + mechanism used to encode this part. The value can be + <command>MAILMIME_MECHANISM_7BIT</command>, + <command>MAILMIME_MECHANISM_8BIT</command>, + <command>MAILMIME_MECHANISM_BINARY</command>, + <command>MAILMIME_MECHANISM_QUOTED_PRINTABLE</command> or + <command>MAILMIME_MECHANISM_BASE64</command> + (see <xref linkend="mailmime-mechanism">). + </para> + </listitem> + <listitem> + <para> + <command>encoded</command> is set to 1 if the part is + already encoded with the mechanism given in + <command>encoding</command>. + </para> + </listitem> + <listitem> + <para> + <command>data</command> is a pointer to the + content of the part. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the length of the data. + </para> + </listitem> + <listitem> + <para> + <command>filename</command> is the name of the file. + </para> + </listitem> + </itemizedlist> + + <example> + <title>creating MIME content</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +#define DATA_STR "my data" + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new_data(MAILMIME_MECHANISM_BASE64, 0, + DATA_STR, sizeof(DATA_STR) - 1); + + /* do the things */ + + mailmime_data_free(data); +} + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new_file(MAILMIME_MECHANISM_BASE64, 0, + strdup("foo-bar.txt")); + + /* do the things */ + + mailmime_data_free(data); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_new_message_data --> + <sect2 id="mailmime-new-message-data"> + <title>mailmime_new_message_data, mailmime_new_empty and + mailmime_new_with_content</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailmime * +mailmime_new_message_data(struct mailmime * msg_mime); + +struct mailmime * +mailmime_new_empty(struct mailmime_content * content, + struct mailmime_fields * mime_fields); + +int +mailmime_new_with_content(const char * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result); + +struct mailmime * mailmime_multiple_new(const char * type); + </programlisting> + + <para> + <command>mailmime_new_message_data()</command> will create a + new MIME message with the given subpart. + </para> + + <para> + <command>mailmime_new_empty()</command> will create a + new MIME part with the given content type and MIME fields + but with no content. + </para> + + <para> + <command>mailmime_new_with_content()</command> will create a + new MIME part with a content type given by a string and a + given MIME fields list. + </para> + + <para> + <command>mailmime_multiple_new()</command> will create a + new MIME multipart with a content type given by a string. + </para> + + <itemizedlist> + <listitem> + <para> + <command>msg_mime</command> is the sub part to add to the + MIME message when creating it + (see <xref linkend="mailmime">). + </para> + </listitem> + <listitem> + <para> + <command>content</command> is the content type of the part + to create + (see <xref linkend="mailmime-content">). + </para> + </listitem> + <listitem> + <para> + <command>content_type</command> is the content type of + the part to create given by a string. + </para> + </listitem> + <listitem> + <para> + <command>mime_fields</command> is the list of MIME + header fields + (see <xref linkend="mailmime-fields">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>creating a MIME part</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +#define DATA_STR "my data" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailmime * single_part; + + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + mailmime_new_with_content("plain/text", mime_fields, &single_part); + + mailmime_set_body_text(single_part, DATA_STR, sizeof(DATA_STR) - 1); + + mime = mailmime_new_message_data(single_part); + + /* do the things */ + + mailmime_free(mime); +} + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailmime * single_part; + struct mailmime_content * content; + + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + content = mailmime_get_content_text(); + single_part = mailmime_new_empty(content, mime_fields); + + mailmime_set_body_text(single_part, DATA_STR, sizeof(DATA_STR) - 1); + + mime = mailmime_new_message_data(single_part); + + /* do the things */ + + mailmime_free(mime); +} + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + + mime = mailmime_multiple_new("multipart/mixed"); + + /* do the things */ + + mailmime_free(mime); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_set_preamble_file --> + <sect2 id="mailmime-set-preamble-file"> + <title>mailmime_set_preamble_file, mailmime_set_epilogue_file, + mailmime_set_preamble_text and mailmime_set_epilogue_text</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_set_preamble_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_epilogue_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_preamble_text(struct mailmime * build_info, + char * data_str, size_t length); + +int mailmime_set_epilogue_text(struct mailmime * build_info, + char * data_str, size_t length); + </programlisting> + + <para> + <command>mailmime_set_preamble_file()</command> will define + the preamble of a multipart. + </para> + + <para> + <command>mailmime_set_preamble_text()</command> will define + the preamble of a multipart. + </para> + + <para> + <command>mailmime_set_epilogue_file()</command> will define + the epilogue of a multipart. + </para> + + <para> + <command>mailmime_set_preamble_text()</command> will define + the preamble of a multipart. + </para> + + <itemizedlist> + <listitem> + <para> + <command>build_info</command> is the MIME part to modify + (see <xref linkend="mailmime">). + </para> + </listitem> + <listitem> + <para> + <command>data_str</command> is the string to define + as epilogue or prologue. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the length of the string to + define as epilogue or prologue. + </para> + </listitem> + <listitem> + <para> + <command>filename</command> is the name of the file + which content will be defined as epilogue or prologue. + </para> + </listitem> + </itemizedlist> + + <example> + <title>setting preamble and epilogue</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +#define DATA_STR "test foo bar" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + + mime = mailmime_multiple_new("multipart/mixed"); + + mailmime_set_preamble_file(mime, strdup("foo-bar.txt")); + + mailmime_set_epilogue_data(mime, DATA_STR, sizeof(DATA_STR) - 1); + + /* do the things */ + + mailmime_free(mime); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_set_body_file --> + <sect2 id="mailmime-set-body-file"> + <title>mailmime_set_body_file and mailmime_set_body_text</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_set_body_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_body_text(struct mailmime * build_info, + char * data_str, size_t length); + </programlisting> + + <para> + <command>mailmime_set_body_file()</command> will define + the body of a single part. + </para> + + <para> + <command>mailmime_set_body_text()</command> will define + the body of a single part. + </para> + + <itemizedlist> + <listitem> + <para> + <command>build_info</command> is the MIME part to modify + (see <xref linkend="mailmime">). + </para> + </listitem> + <listitem> + <para> + <command>data_str</command> is the string to define + as the body of the part. + </para> + </listitem> + <listitem> + <para> + <command>length</command> is the length of the string to + define as the body of the part. + </para> + </listitem> + <listitem> + <para> + <command>filename</command> is the name of the file + which content will be defined as the body of the part. + </para> + </listitem> + </itemizedlist> + + <example> + <title>creating a MIME part</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +#define DATA_STR "my data" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + mailmime_new_with_content("plain/text", mime_fields, &mime); + + mailmime_set_body_text(mime, DATA_STR, sizeof(DATA_STR) - 1); + + + + /* do the things */ + + mailmime_free(mime); +} + </programlisting> + </example> + + </sect2> + + <!-- mailmime_add_part --> + <sect2 id="mailmime-add-part"> + <title>mailmime_add_part, mailmime_remove_part, + mailmime_smart_add_part and mailmime_smart_remove_part</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_add_part(struct mailmime * build_info, + struct mailmime * part); + +void mailmime_remove_part(struct mailmime * mime); + +int mailmime_smart_add_part(struct mailmime * mime, + struct mailmime * mime_sub); + +int mailmime_smart_remove_part(struct mailmime * mime); + </programlisting> + + <para> + <command>mailmime_add_part()</command> will add a sub MIME + part. + </para> + + <para> + <command>mailmime_remove_part()</command> will detach the + given sub part from its parent. + </para> + + <para> + <command>mailmime_smart_add_part()</command> will add a sub + MIME part. If the parent part is a message and no child + exist, the part is set as the child. If the parent part is a + message and a child already exists, if the child is + multipart, the part to add is added as child of this + multipart, else a multipart is added and the part is added + as child of the multipart. + </para> + + <para> + <command>mailmime_smart_remove_part()</command> will detach + the given sub part from its parent. The sub part will be + freed. + </para> + + <itemizedlist> + <listitem> + <para> + <command>build_info</command> is the parent MIME part + (see <xref linkend="mailmime">). + </para> + </listitem> + <listitem> + <para> + <command>part</command> is the part to add + (see <xref linkend="mailmime">). + </para> + </listitem> + <listitem> + <para> + <command>mime</command> is the parent MIME part + (see <xref linkend="mailmime">). + </para> + </listitem> + <listitem> + <para> + <command>mime_sub</command> is the part to add or to + detach + (see <xref linkend="mailmime">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>modifying MIME structure</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_add_part(mime, sub_mime); + + /* do the things */ + + mailmime_free(mime); + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime * other_sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + sub_mime = mailmime_new_empty(content, mime_fields); + + content = mailmime_get_content_text(); + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + other_sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_smart_add_part(mime, sub_mime); + mailmime_smart_add_part(mime, other_sub_mime); + + /* do the things */ + + mailmime_free(mime); + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_add_part(mime, sub_mime); + + mailmime_remove_part(sub_mime); + + /* do the things */ + + mailmime_free(sub_mime); + mailmime_free(mime); + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_add_part(mime, sub_mime); + + mailmime_smart_remove_part(sub_mime); + + /* do the things */ + + mailmime_free(mime); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_set_imf_fields --> + <sect2 id="mailmime-set-imf-fields"> + <title>mailmime_set_imf_fields</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +void mailmime_set_imf_fields(struct mailmime * build_info, + struct mailimf_fields * fields); + </programlisting> + + <para> + <command>mailmime_set_imf_fields()</command> will set the + fields of the given MIME message. + </para> + + <itemizedlist> + <listitem> + <para> + <command>build_info</command> is the MIME message to + modify + (see <xref linkend="mailmime">). + </para> + </listitem> + <listitem> + <para> + <command>fields</command> is the header fields to set + for the message + (see <xref linkend="mailimf-fields">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>modifying MIME structure</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +#define DATA_STR "test foo bar" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailmime_fields * mime_fields; + struct mailimf_fields * imf_fields; + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT); + + mailmime_new_with_content("text/plain", mime_fields, &mime); + + mailmime_set_body_text(mime, DATA_STR, sizeof(DATA_STR) - 1); + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + imf_fields = build_fields(); + + mailmime_set_imf_fields(mime, imf_fields); + + /* do the things */ + + mailmime_free(mime); +} + </programlisting> + </example> + </sect2> + + <!-- mailmime_fields_new_encoding --> + <sect2 id="mailmime-fields-new-encoding"> + <title>mailmime_fields_new_encoding and + mailmime_fields_new_filename</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_fields * mailmime_fields_new_encoding(int encoding_type); + +struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, + char * filename, int encoding_type); + </programlisting> + + <para> + <command>mailmime_fields_new_encoding()</command> will + create a list of MIME header fields with only + <command>Content-Transfer-Encoding</command>. + </para> + + <para> + <command>mailmime_fields_new_filename()</command> will + create a list of MIME header fields with + <command>Content-Transfer-Encoding</command> and + <command>Content-Disposition</command>. + </para> + + <para> + The result will be a list of MIME header fields + (see <xref linkend="mailmime-fields">). + </para> + + <itemizedlist> + <listitem> + <para> + <command>encoding_type</command> is the MIME encoding + mechanism. The value can be + <command>MAILMIME_MECHANISM_7BIT</command>, + <command>MAILMIME_MECHANISM_8BIT</command>, + <command>MAILMIME_MECHANISM_BINARY</command>, + <command>MAILMIME_MECHANISM_QUOTED_PRINTABLE</command> or + <command>MAILMIME_MECHANISM_BASE64</command> + (see <xref linkend="mailmime-mechanism">). + </para> + </listitem> + <listitem> + <para> + <command>dsp_type</command> is the disposition type. + The value can be + <command>MAILMIME_DISPOSITION_TYPE_INLINE</command> or + <command>MAILMIME_DISPOSITION_TYPE_ATTACHMENT</command> + (see <xref linkend="mailmime-disposition-type">). + </para> + </listitem> + <listitem> + <para> + <command>filename</command> is the filename for MIME + content disposition. + </para> + </listitem> + </itemizedlist> + + <example> + <title>creating MIME fields with only Content-Transfer-Encoding</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int main(void) +{ + struct mailmime_fields * fields; + + fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + /* do the things */ + + mailmime_fields_free(fields); +} + +int main(void) +{ + struct mailmime_fields * fields; + + fields = + mailmime_fields_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + strdup("foo-bar.txt"), MAILMIME_MECHANISM_BASE64); + + /* do the things */ + + mailmime_fields_free(fields); +} + </programlisting> + </example> + </sect2> + </sect1> + + <!-- Helper functions --> + <sect1> + <title>Helper functions</title> + + <!-- mailmime_transfer_encoding_get --> + <sect2 id="mailmime-transfer-encoding-get"> + <title>mailmime_transfer_encoding_get</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmime_transfer_encoding_get(struct mailmime_fields * fields); + </programlisting> + + <para> + <command>mailmime_transfer_encoding_get()</command> will + return the standard MIME encoding mechanism. + </para> + + <itemizedlist> + <listitem> + <para> + <command>fields</command> is the list of MIME header + fields. + </para> + </listitem> + <listitem> + <para> + An integer representing the MIME encoding mechanism will + be returned + (see <xref linkend="mailmime-mechanism">). + </para> + </listitem> + </itemizedlist> + + <example> + <title>extracting MIME encoding mechanism</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + struct mailmime_fields * mime_fields; + + r = mailmime_fields_parse(f, &mime_fields); + if (r == MAILIMF_NO_ERROR) { + int encoding; + + encoding = mailmime_transfer_encoding_get(mime_fields); + + /* do the things */ + + mailmime_fields_free(mime_fields); + status = EXIT_SUCCESS; + } + + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + + </sect2> + + <!-- mailmime_content_charset_get --> + <sect2 id="mailmime-content-charset-get"> + <title>mailmime_content_charset_get and + mailmime_content_param_get</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +char * mailmime_content_charset_get(struct mailmime_content * content); + +char * mailmime_content_param_get(struct mailmime_content * content, + char * name); + +char * mailmime_extract_boundary(struct mailmime_content * content_type); + </programlisting> + + <para> + <command>mailmime_content_charset_get()</command> will + return the <command>charset</command> parameter of + MIME content type. + </para> + + <para> + <command>mailmime_content_param_get()</command> will + return the value of a given parameter of + MIME content type. + </para> + + <para> + <command>mailmime_extract_boundary()</command> will + return the <command>charset</command> parameter of + MIME content type. + </para> + + <itemizedlist> + <listitem> + <para> + <command>content</command> is the MIME content type. + </para> + </listitem> + <listitem> + <para> + <command>name</command> is the name of the parameter to + extract. + </para> + </listitem> + <listitem> + <para> + With <command>mailmime_extract_boundary()</command>, the + returned value must be freed with + <command>free()</command>. + </para> + </listitem> + </itemizedlist> + + <example> + <title>extracting information from MIME content type</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Type") == 0) { + struct mailmime_content * content_type; + size_t current_index; + + current_index = 0; + r = mailmime_content_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &content_type); + if (r == MAILIMF_NO_ERROR) { + char * charset; + char * name; + char * boundary; + + charset = mailmime_content_charset_get(content_type); + name = mailmime_content_param_get(content_type, "name"); + boundary = mailmime_extract_boundary(content_type); + + /* do the things */ + + free(boundary); + + status = EXIT_SUCCESS; + mailmime_content_free(content_type); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </programlisting> + </example> + </sect2> + </sect1> + </chapter> + + <!-- Storages, folders, messages --> + <chapter> + <title>Storages, folders, messages</title> + + <!-- Introduction --> + <sect1> + <title>Introduction</title> + + <para> + This part will give the definition of some objects. + </para> + + <sect2> + <title>Message</title> + + <para> + A message is the common e-mail message or news message you + read or send. + </para> + </sect2> + + <sect2> + <title>MIME part</title> + + <para> + A message can have attachment such as images or other documents. + The attachment are organized into a tree structure. Each + node of this structure is a MIME part. + </para> + </sect2> + + <sect2> + <title>Mailbox</title> + + <para> + A mailbox will contain a given number of messages. + </para> + </sect2> + + <sect2> + <title>Storage</title> + + <para> + A storage is a "physical" localisation of your mailbox. This + can be on a filesystem (local or remote disk, this is the + case of MH, mbox and maildir), or this can be on a remote + host (this is the case for POP3, IMAP or NNTP). + </para> + </sect2> + + <sect2> + <title>Folder</title> + + <para> + A storage, for the same user, can contain a given number of + mailboxes, depending the storage capabilities, then, the + storage driver capabilities. With etPan!, MH, IMAP and NNTP + storages can have more than one mailbox. The mailboxes will + be called folders. On storage where we only have one + mailbox, the unique mailbox is the unique folder. + </para> + </sect2> + + <sect2> + <title>Session</title> + + <para> + The session is the network connection or the entity to which + the commands of the drivers are given. + </para> + </sect2> + </sect1> + + <sect1> + <title>Error codes</title> + + <para> + Error codes returned as integers can be one of the following : + </para> + + <programlisting role="C"> +enum { + MAIL_NO_ERROR = 0, + MAIL_NO_ERROR_AUTHENTICATED, + MAIL_NO_ERROR_NON_AUTHENTICATED, + MAIL_ERROR_NOT_IMPLEMENTED, + MAIL_ERROR_UNKNOWN, + MAIL_ERROR_CONNECT, + MAIL_ERROR_BAD_STATE, + MAIL_ERROR_FILE, + MAIL_ERROR_STREAM, + MAIL_ERROR_LOGIN, + MAIL_ERROR_CREATE, /* 10 */ + MAIL_ERROR_DELETE, + MAIL_ERROR_LOGOUT, + MAIL_ERROR_NOOP, + MAIL_ERROR_RENAME, + MAIL_ERROR_CHECK, + MAIL_ERROR_EXAMINE, + MAIL_ERROR_SELECT, + MAIL_ERROR_MEMORY, + MAIL_ERROR_STATUS, + MAIL_ERROR_SUBSCRIBE, /* 20 */ + MAIL_ERROR_UNSUBSCRIBE, + MAIL_ERROR_LIST, + MAIL_ERROR_LSUB, + MAIL_ERROR_APPEND, + MAIL_ERROR_COPY, + MAIL_ERROR_FETCH, + MAIL_ERROR_STORE, + MAIL_ERROR_SEARCH, + MAIL_ERROR_DISKSPACE, + MAIL_ERROR_MSG_NOT_FOUND, /* 30 */ + MAIL_ERROR_PARSE, + MAIL_ERROR_INVAL, + MAIL_ERROR_PART_NOT_FOUND, + MAIL_ERROR_REMOVE, + MAIL_ERROR_FOLDER_NOT_FOUND, + MAIL_ERROR_MOVE, + MAIL_ERROR_STARTTLS, + MAIL_ERROR_CACHE_MISS, + MAIL_ERROR_NO_TLS, + MAIL_ERROR_EXPUNGE, + /* misc errors */ + MAIL_ERROR_MISC, + MAIL_ERROR_PROTOCOL, + MAIL_ERROR_CAPABILITY, + MAIL_ERROR_CLOSE, + MAIL_ERROR_FATAL, + MAIL_ERROR_READONLY, + MAIL_ERROR_NO_APOP, + MAIL_ERROR_COMMAND_NOT_SUPPORTED, + MAIL_ERROR_NO_PERMISSION, + MAIL_ERROR_PROGRAM_ERROR, + MAIL_ERROR_SUBJECT_NOT_FOUND, + MAIL_ERROR_CHAR_ENCODING_FAILED, + MAIL_ERROR_SEND, + MAIL_ERROR_COMMAND, +}; + </programlisting> + </sect1> + + <!-- Storage --> + <sect1> + <title>Storage</title> + + <sect2 id="mailstorage-driver"> + <title>Storage driver</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +typedef struct mailstorage_driver mailstorage_driver; + +struct mailstorage_driver { + char * sto_name; + int (* sto_connect)(struct mailstorage * storage); + int (* sto_get_folder_session)(struct mailstorage * storage, + char * pathname, mailsession ** result); + void (* sto_uninitialize)(struct mailstorage * storage); +}; + </programlisting> + + <para> + This is the driver for a storage. + </para> + + <itemizedlist> + <listitem> + <para> + <command>sto_name</command> is the name of the driver. + </para> + </listitem> + <listitem> + <para> + <command>sto_connect()</command> connects the storage to + the remote access or to the path in the local filesystem. + </para> + </listitem> + <listitem> + <para> + <command>sto_get_folder_session()</command> can have two + kinds of behaviour. Either it creates a new session and + independant from the session used by the storage and + select the given mailbox or it selects the given mailbox + in the current session. It depends on the efficiency of + the mail access. + </para> + <para> + <emphasis>XXX - in the future, this will be moved to the + folder driver</emphasis> + </para> + </listitem> + <listitem> + <para> + <command>sto_uninitialize()</command> frees the data + created with mailstorage constructor. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2 id="mailstorage"> + <title>Storage</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailstorage { + char * sto_id; + void * sto_data; + mailsession * sto_session; + mailstorage_driver * sto_driver; + clist * sto_shared_folders; /* list of (struct mailfolder *) */ + + void * sto_user_data; +}; + </programlisting> + + <itemizedlist> + <listitem> + <para> + <command>sto_id</command> is an identifier for the + storage. This can be <command>NULL</command>. + </para> + </listitem> + <listitem> + <para> + <command>sto_data</command> is the internal data + of the storage. This can only be changed by the driver. + </para> + </listitem> + <listitem> + <para> + <command>sto_session</command> is the session used by + the storage. The session can be used to send commands. + </para> + </listitem> + <listitem> + <para> + <command>sto_driver</command> is the driver of the + storage. + </para> + </listitem> + <listitem> + <para> + <command>sto_shared_folders</command> is the list of + folders that share the session with the storage. + This is used internally. + </para> + </listitem> + <listitem> + <para> + <command>sto_user_data</command> is a field for free + use. The user can store any data in that field. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2 id="mailstorage-new"> + <title>mailstorage_new and mailstorage_free</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailstorage * mailstorage_new(char * sto_id); + +void mailstorage_free(struct mailstorage * storage); + </programlisting> + + <para> + <command>mailstorage_new()</command> initializes a storage + structure with an identifier (<command>sto_id</command>) and + with no driver. + </para> + + <para> + <command>mailstorage_free()</command> free the memory used + by a storage. + </para> + </sect2> + + <sect2 id="mailstorage-connect"> + <title>mailstorage_connect and mailstorage_disconnect</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailstorage_connect(struct mailstorage * storage); + +void mailstorage_disconnect(struct mailstorage * storage); + </programlisting> + + <para> + <command>mailstorage_connect()</command> connects the storage. + This function can also be used to confirm that a storage + connection is valid when the storage is already connected. + </para> + + <para> + <command>mailstorage_disconnect()</command> disconnects the + storage. + </para> + </sect2> + + <sect2> + <title>IMAP storage</title> + + <programlisting role="C"> +int imap_mailstorage_init(struct mailstorage * storage, + char * imap_servername, uint16_t imap_port, + char * imap_command, + int imap_connection_type, int imap_auth_type, + char * imap_login, char * imap_password, + int imap_cached, char * imap_cache_directory); + </programlisting> + </sect2> + + <sect2> + <title>Example</title> + + <example> + <title>use of storage</title> + + <programlisting role="C"> +int main(void) +{ + struct mailstorage * storage; + int r; + + storage = mailstorage_new(NULL); + + imap_mailstorage_init(storage, "imap.my-servers.org", 0, + NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN, + "my-login", "my-password", 1, "/home/login/.libetpan/cache"); + + r = mailstorage_connect(storage); + if (r == MAIL_NO_ERROR) { + mailstorage_disconnect(storage); + } + + mailstorage_free(storage); +} + </programlisting> + </example> + </sect2> + </sect1> + + <!-- Folder --> + <sect1> + <title>Folder</title> + + <sect2 id="mailfolder-driver"> + <title>Folder driver</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +typedef struct mailfolder_driver mailfolder_driver; + +struct mailfolder_driver { + int (* fld_get_session)(struct mailfolder * folder, + mailsession ** result); + + int (* fld_noop)(struct mailfolder * folder); + + int (* fld_check)(struct mailfolder * folder); + + int (* fld_expunge)(struct mailfolder * folder); + + int (* fld_status)(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + + int (* fld_append_message)(struct mailfolder * folder, + char * message, size_t size); + + int (* fld_get_messages_list)(struct mailfolder * folder, + struct mailmessage_list ** result); + + int (* fld_get_envelopes_list)(struct mailfolder * folder, + struct mailmessage_list * result); + + int (* fld_get_message)(struct mailfolder * folder, + uint32_t num, mailmessage ** result); + + int (* fld_get_message_by_uid)(struct mailfolder * folder, + const char * uid, mailmessage ** result); +} + </programlisting> + + <para> + XXX - this will be implemented in the future. + </para> + + <itemizedlist> + <listitem> + <para> + <command>fld_get_session()</command> will return the session + this folder should use. + </para> + </listitem> + <listitem> + <para> + For other method, you should see <xref + linkend="mailsession-driver">. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Folder</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailfolder { + char * fld_pathname; + char * fld_virtual_name; + + struct mailstorage * fld_storage; + + mailsession * fld_session; + int fld_shared_session; + clistiter * fld_pos; + + struct mailfolder * fld_parent; + unsigned int fld_sibling_index; + carray * fld_children; /* array of (struct mailfolder *) */ + + void * fld_user_data; +}; + </programlisting> + + <itemizedlist> + <listitem> + <para> + <command>fld_pathname</command> is the pathname specific to + the driver. + </para> + </listitem> + + <listitem> + <para> + <command>fld_virtual_name</command> is the identifier of + this folder. This can be <command>NULL</command>. + </para> + </listitem> + + <listitem> + <para> + <command>fld_storage</command> is the storage used for this + folder (see <xref linkend="mailstorage">). + </para> + </listitem> + + <listitem> + <para> + <command>fld_session</command> is the session used for this + folder. + </para> + </listitem> + + <listitem> + <para> + <command>fld_shared_session</command> is set to 1 if the + folder use the same session as the storage. This is used + internally. + </para> + </listitem> + + <listitem> + <para> + <command>fld_pos</command> is the + position in the list of folders of the storage. + This is used internally. + </para> + </listitem> + + <listitem> + <para> + use of <command>fld_parent</command>, + <command>fld_sibling_index</command> and + <command>fld_children</command> is deprecated. + </para> + </listitem> + + <listitem> + <para> + <command>fld_user_data</command> is a field for free + use. The user can store any data in that field. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2 id="mailfolder-new"> + <title>mailfolder_new and mail_folder_free</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailfolder * mailfolder_new(struct mailstorage * fld_storage, + char * fld_pathname, char * fld_virtual_name); + +void mailfolder_free(struct mailfolder * folder); + </programlisting> + + <para> + <command>mailfolder_new()</command> initializes a folder + structure with an identifier + (<command>fld_virtual_name</command>) with path name + (<command>fld_pathname</command>). The folder will be owned + by the given storage (<command>fld_storage</command>). + </para> + + <para> + <command>mailfolder_free()</command> free the memory used + by the folder. + </para> + </sect2> + + <sect2 id="mailfolder-connect"> + <title>mailfolder_connect and mailfolder_disconnect</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailfolder_connect(struct mailfolder * folder); + +void mailfolder_disconnect(struct mailfolder * folder); + </programlisting> + + <para> + <command>mailfolder_connect()</command> connects the folder. + This function can also be used to confirm that a folder + connection is valid when the folder is already connected. + When doing operations with several folders, you have to be + sure that this function has been called before making calls + on folder. + </para> + + <para> + <command>mailfolder_disconnect()</command> disconnects the + folder. + </para> + </sect2> + + <sect2 id="mailfolder-noop"> + <title>mailfolder_noop</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailfolder_noop(struct mailfolder * folder); + </programlisting> + + <para> + This function will only send noop to the mail access. + </para> + </sect2> + + <sect2 id="mailfolder-check"> + <title>mailfolder_check</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailfolder_check(struct mailfolder * folder); + </programlisting> + + <para> + A call to this function will save to disk the internal state + of the selected mailbox (such as flags). + </para> + </sect2> + + <sect2 id="mailfolder-expunge"> + <title>mailfolder_expunge</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailfolder_expunge(struct mailfolder * folder); + </programlisting> + + <para> + A call to this function will delete all messages marked for + deletion. + </para> + </sect2> + + <sect2 id="mailfolder-status"> + <title>mailfolder_status</title> + + <programlisting role="C"> +int mailfolder_status(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + </programlisting> + + <para> + A call to this function will return some counts of messages + in the mailbox. + </para> + </sect2> + + <sect2 id="mailfolder-append-message"> + <title>mailfolder_append_message</title> + + <programlisting role="C"> +int mailfolder_append_message(struct mailfolder * folder, + char * message, size_t size); + </programlisting> + + <para> + This function will store a new message in the given folder. + The message is given by a string in memory + (<command>message</command>) and a size + (<command>size</command>). + </para> + </sect2> + + <sect2 id="mailfolder-get-messages-list"> + <title>mailfolder_get_messages_list</title> + + <programlisting role="C"> +int mailfolder_get_messages_list(struct mailfolder * folder, + struct mailmessage_list ** result); + </programlisting> + + <para> + This function will return the list of messages in the given + folder (see <xref linkend="mailmessage-list">). + </para> + </sect2> + + <sect2 id="mailfolder-get-envelopes-list"> + <title>mailfolder_get_envelopes_list</title> + + <programlisting role="C"> +int mailfolder_get_envelopes_list(struct mailfolder * folder, + struct mailmessage_list * result); + </programlisting> + + <para> + This function will fill the list of parsed header fields + structure in the <command>mailmessage</command> structures + of the given list of messages (<command>result</command>). + </para> + </sect2> + + <sect2 id="mailfolder-get-message"> + <title>mailfolder_get_message</title> + + <programlisting role="C"> +int mailfolder_get_message(struct mailfolder * folder, + uint32_t num, mailmessage ** result); + </programlisting> + + <para> + This function will return the message identified by a + message index (<command>num</command>) + This will return a <command>mailmessage</command> structure + in <command>(* result)</command> (see <xref + linkend="mailmessage">). + </para> + </sect2> + + <sect2 id="mailfolder-get-message-by-uid"> + <title>mailfolder_get_message_by_uid</title> + + <programlisting role="C"> +int mailfolder_get_message_by_uid(struct mailfolder * folder, + const char * uid, mailmessage ** result); + </programlisting> + + <para> + This function will return the message identified by a + unique identifier (<command>uid</command>) + This will return a <command>mailmessage</command> structure + in <command>(* result)</command> (see <xref + linkend="mailmessage">). + </para> + </sect2> + + <sect2> + <title>Example</title> + + <example> + <title>use of folder</title> + + <programlisting role="C"> +int main(void) +{ + struct mailstorage * storage; + int r; + + storage = mailstorage_new(NULL); + + imap_mailstorage_init(storage, "imap.my-servers.org", 0, + NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN, + "my-login", "my-password", 1, "/home/login/.libetpan/cache"); + + r = mailstorage_connect(storage); + if (r == MAIL_NO_ERROR) { + struct mailfolder * folder; + + folder = mailfolder_new(storage, "INBOX", NULL); + + r = mailfolder_connect(folder); + if (r == MAIL_NO_ERROR) { + struct mailmessage_list * msg_list; + + mailfolder_get_messages_list(folder, &msg_list); + + /* do the things */ + + mailmessage_list_free(msg_list); + + mailfolder_disconnect(folder); + } + + mailstorage_disconnect(storage); + } + + mailstorage_free(storage); +} + </programlisting> + </example> + </sect2> + + </sect1> + + <!-- Message --> + <sect1> + <title>Message</title> + + <sect2 id="mailmessage-driver"> + <title>Message driver</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailmessage_driver { + char * msg_name; + + int (* msg_initialize)(mailmessage * msg_info); + + void (* msg_uninitialize)(mailmessage * msg_info); + + void (* msg_flush)(mailmessage * msg_info); + + void (* msg_check)(mailmessage * msg_info); + + void (* msg_fetch_result_free)(mailmessage * msg_info, + char * msg); + + int (* msg_fetch)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_header)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_body)(mailmessage * msg_info, + char ** result, size_t * result_len); + + int (* msg_fetch_size)(mailmessage * msg_info, + size_t * result); + + int (* msg_get_bodystructure)(mailmessage * msg_info, + struct mailmime ** result); + + int (* msg_fetch_section)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + + int (* msg_fetch_section_header)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_mime)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_body)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_envelope)(mailmessage * msg_info, + struct mailimf_fields ** result); + + int (* msg_get_flags)(mailmessage * msg_info, + struct mail_flags ** result); +}; + </programlisting> + + <itemizedlist> + <listitem> + <para> + <command>msg_name</command> is the name of the driver. + </para> + </listitem> + + <listitem> + <para> + <command>msg_initialize()</command> will initialize the + internal message state (field + <command>msg_data</command> of + <command>mailmessage</command> structure (see <xref + linkend="mailmessage">). + </para> + </listitem> + + <listitem> + <para> + <command>msg_uninitialize()</command> will free the + internal message state. + </para> + </listitem> + + <listitem> + <para> + <command>msg_flush()</command> will release memory used + by the MIME structure of the message. + </para> + </listitem> + + <listitem> + <para> + <command>msg_check()</command> will store the flags of + the message into the session, so that the message can be + released without the flags are lost. + </para> + </listitem> + + <listitem> + <para> + <command>msg_fetch_result_free()</command> will free a + string returned by any fetch_XXX() function. + </para> + </listitem> + + <listitem> + <para> + <command>msg_fetch()</command> will fetch a message. + </para> + </listitem> + + <listitem> + <para> + <command>msg_fetch_header()</command> will fetch the + header fields of a message. + </para> + </listitem> + + <listitem> + <para> + <command>msg_fetch_body()</command> will fetch a message + without its main header. + </para> + </listitem> + + <listitem> + <para> + <command>msg_fetch_size()</command> will return the size + of a message. + </para> + </listitem> + + <listitem> + <para> + <command>msg_get_bodystructure</command> will retrieve + the MIME structure of the message. The returned + structure must <emphasis>NOT</emphasis> be freed. + </para> + </listitem> + + <listitem> + <para> + <command>msg_fetch_section()</command> will fetch the + content of the section of the message. + </para> + </listitem> + + <listitem> + <para> + <command>msg_fetch_section_header()</command> will fetch + the header of a section of the message if the content of + the section is a message. + </para> + </listitem> + + <listitem> + <para> + <command>msg_fetch_section_mime()</command> will fetch + the MIME header of a section of the message. + </para> + </listitem> + + <listitem> + <para> + <command>msg_fetch_section_body()</command> will fetch + the body of a section (without the headers) of the + message if the content of the section is a message. + </para> + </listitem> + + <listitem> + <para> + <command>msg_fetch_envelope()</command> will return + a given number of parsed header fields. + </para> + </listitem> + + <listitem> + <para> + <command>msg_get_flags()</command> will return the + flags of the message. + The returned structure must <emphasis>NOT</emphasis> be + freed. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2 id="mailmessage"> + <title>Message</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailmessage { + mailsession * msg_session; + mailmessage_driver * msg_driver; + uint32_t msg_index; + char * msg_uid; + + size_t msg_size; + struct mailimf_fields * msg_fields; + struct mail_flags * msg_flags; + + int msg_resolved; + struct mailimf_single_fields msg_single_fields; + struct mailmime * msg_mime; + + /* internal data */ + + int msg_cached; + void * msg_data; + + /* + msg_folder field : + used to reference the mailfolder, this is a workaround due + to the problem with initial conception, where folder notion + did not exist. + */ + void * msg_folder; + /* user data */ + void * msg_user_data; +}; + </programlisting> + + <itemizedlist> + <listitem> + <para> + <command>msg_session</command> is the session related to + the message + (see <xref linkend="mailsession">). + </para> + </listitem> + + <listitem> + <para> + <command>msg_driver</command> is the driver used for the + message + (see <xref linkend="mailmessage-driver">). + </para> + </listitem> + + <listitem> + <para> + <command>msg_index</command> is an index to indentify + the message. + </para> + </listitem> + + <listitem> + <para> + <command>msg_uid</command> is the unique identifier of + the message, valid accross disconnections. + </para> + </listitem> + + <listitem> + <para> + <command>msg_size</command> is the size of the message. + </para> + </listitem> + + <listitem> + <para> + <command>msg_fields</command> is the list of parsed + header fields of the message. This can be + <command>NULL</command> + (see <xref linkend="mailimf-fields">). + </para> + </listitem> + + <listitem> + <para> + <command>msg_flags</command> is the flags of the + message. This can be <command>NULL</command> + (see <xref linkend="mail-flags">). + </para> + </listitem> + + <listitem> + <para> + <command>msg_resolved</command> will tell if the field + <command>msg_single_fields</command> has been initialized. + </para> + </listitem> + + <listitem> + <para> + <command>msg_single_fields</command> will be filled + using <command>msg_fields</command> + (see <xref linkend="mailimf-single-fields">). + </para> + </listitem> + + <listitem> + <para> + <command>msg_mime</command> is the MIME structure of the + message. It is intialized at least when + <command>get_bodystructure()</command> is called once. + </para> + </listitem> + + <listitem> + <para> + <command>msg_cached</command> is 1 when the message was + cached. This is used internally. + </para> + </listitem> + + <listitem> + <para> + <command>msg_data</command> is the internal state of the + message. The content depends on the driver. + </para> + </listitem> + + <listitem> + <para> + <command>msg_folder</command> is used to reference the + mailfolder, this is a workaround due to the problem with + initial conception, where folder notion did not exist. + </para> + </listitem> + + <listitem> + <para> + <command>msg_user_data</command> is a field for free + use. The user can store any data in that field. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2 id="mailmessage-new"> + <title>mailmessage_new</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +mailmessage * mailmessage_new(void); + +void mailmessage_free(mailmessage * info); + </programlisting> + + <para> + <command>mailmessage_new()</command> will create a new + message (without driver). This is used internally by + drivers. + </para> + + <para> + <command>mailmessage_free()</command> will free the memory + used by the given message. + </para> + </sect2> + + <sect2 id="mailmessage-init"> + <title>mailmessage_init</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmessage_init(mailmessage * msg_info, + mailsession * session, + mailmessage_driver * driver, + uint32_t index, size_t size); + </programlisting> + + <para> + <command>mailmessage_init()</command> will initialize a + message with a driver. + </para> + + <itemizedlist> + <listitem> + <para> + <command>msg_info</command> is the message to initialize + (see <xref linkend="mailmessage">). + </para> + </listitem> + + <listitem> + <para> + <command>session</command> is the session related to the + message + (see <xref linkend="mailsession">). + </para> + </listitem> + + <listitem> + <para> + <command>driver</command> is the driver to use for the + message + (see <xref linkend="mailmessage-driver">). + </para> + </listitem> + + <listitem> + <para> + <command>index</command> is the index of the message. + </para> + </listitem> + + <listitem> + <para> + <command>size</command> is the size of the message. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2 id="mailmessage-flush"> + <title>mailmessage_flush</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmessage_flush(mailmessage * info); + </programlisting> + + <para> + This function will release the memory used by the MIME + structure of the message. + </para> + </sect2> + + <sect2 id="mailmessage-check"> + <title>mailmessage_check</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmessage_check(mailmessage * info); + </programlisting> + + <para> + After you set some flags, if you want to notify them to the + session before destroying the message, you can use this function. + </para> + </sect2> + + <sect2 id="mailmessage-fetch-result-free"> + <title>mailmessage_fetch_result_free</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmessage_fetch_result_free(mailmessage * msg_info, + char * msg); + </programlisting> + + <para> + This function will free a string returned by any + mailmessage_fetch_XXX() function. + </para> + </sect2> + + <sect2 id="mailmessage-fetch"> + <title>mailmessage_fetch</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmessage_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + </programlisting> + + <para> + This function returns the content of the message (headers + and text). + </para> + </sect2> + + <sect2 id="mailmessage-fetch-header"> + <title>mailmessage_fetch_header</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmessage_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + </programlisting> + + <para> + This function returns the header of the message as a string. + </para> + + </sect2> + + <sect2 id="mailmessage-fetch-body"> + <title>mailmessage_fetch_body</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmessage_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + </programlisting> + + <para> + This function returns the content of the message (without + headers). + </para> + </sect2> + + <sect2 id="mailmessage-fetch-size"> + <title>mailmessage_fetch_size</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmessage_fetch_size(mailmessage * msg_info, + size_t * result); + </programlisting> + + <para> + This function returns the size of the message content. + </para> + </sect2> + + <sect2 id="mailmessage-get-bodystructure"> + <title>mailmessage_get_bodystructure</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmessage_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + </programlisting> + + <para> + This functions returns the MIME structure of the message. + The returned information <emphasis>MUST</emphasis> not be + freed by hand. It is freed by + <command>mailmessage_flush()</command> or + <command>mailmessage_free()</command> + (see <xref linkend="mailmime">). + </para> + </sect2> + + <sect2 id="mailmessage-fetch-section"> + <title>mailmessage_fetch_section</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmessage_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + </programlisting> + + <para> + This function returns the content of a MIME part. + </para> + </sect2> + + <sect2 id="mailmessage-fetch-section-header"> + <title>mailmessage_fetch_section_header</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmessage_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + </programlisting> + + <para> + This function returns the header of the message contained + in the given MIME part. + </para> + </sect2> + + <sect2 id="mailmessage-fetch-section-mime"> + <title>mailmessage_fetch_section_mime</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmessage_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + </programlisting> + + <para> + This function returns the MIME header of the given MIME + part. + </para> + </sect2> + + <sect2 id="mailmessage-fetch-section-body"> + <title>mailmessage_fetch_section_body</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmessage_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + </programlisting> + + <para> + This function returns the text part of the message contained + in the given MIME part. + </para> + </sect2> + + <sect2 id="mailmessage-fetch-envelope"> + <title>mailmessage_fetch_envelope</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmessage_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + </programlisting> + </sect2> + + <sect2 id="mailmessage-get-flags"> + <title>mailmessage_get_flags</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +int mailmessage_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + </programlisting> + + <para> + This function returns the flags related to the message. + The returned information MUST not be freed by hand. It is freed by + <command>mailmessage_free()</command>. + </para> + </sect2> + + <sect2 id="mailmessage-resolve-single-fields"> + <title>mailmessage_resolve_single_fields</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +void mailmessage_resolve_single_fields(mailmessage * msg_info); + </programlisting> + + <para> + This function will use the fields information to fill + the single_fields structure in the mailmessage structure. + </para> + </sect2> + + <sect2 id="mailmessage-list"> + <title>Message list</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailmessage_list { + carray * msg_tab; /* elements are (mailmessage *) */ +}; + +struct mailmessage_list * mailmessage_list_new(carray * msg_tab); + +void mailmessage_list_free(struct mailmessage_list * env_list); + </programlisting> + + <para> + This is a list of messages. + </para> + + <para> + <command>msg_tab</command> is an array containing the + messages (see linkend="carray"). + </para> + + <para> + <command>mailmessage_list_new()</command> will initialize a + list of messages, using a given array of messages. + </para> + + <para> + <command>mailmessage_list_free()</command> will free the + memory used by the list of messages. This will also free the + messages. + </para> + </sect2> + + <sect2 id="mailmessage-tree"> + <title>Message tree</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailmessage_tree { + struct mailmessage_tree * node_parent; + char * node_msgid; + time_t node_date; + mailmessage * node_msg; + carray * node_children; /* array of (struct mailmessage_tree *) */ + + /* private, used for threading */ + int node_is_reply; + char * node_base_subject; +}; + + +struct mailmessage_tree * +mailmessage_tree_new(char * node_msgid, time_t node_date, + mailmessage * node_msg); + +void mailmessage_tree_free(struct mailmessage_tree * tree); + +void mailmessage_tree_free_recursive(struct mailmessage_tree * tree); + </programlisting> + + <para> + This is a node of a tree of messages. + </para> + + <itemizedlist> + <listitem> + <para> + <command>node_parent</command> is the parent of this + node. + </para> + </listitem> + + <listitem> + <para> + <command>node_msgid</command> is the content of the + field <command>Message-ID</command> of the message. + </para> + </listitem> + + <listitem> + <para> + <command>node_date</command> is the date in UNIX + format. + </para> + </listitem> + + <listitem> + <para> + <command>node_msg</command> is the message of the node. + The message should have the <command>msg_fields</command> + field initialized. + </para> + </listitem> + + <listitem> + <para> + <command>node_children</command> is the list of + children of this node. + </para> + </listitem> + + <listitem> + <para> + <command>node_is_reply</command> is set to 1 if the + message is a reply. + </para> + </listitem> + + <listitem> + <para> + <command>node_base_subject</command> is the base subject + of the message (base subject is defined in definition of + IMAP thread draft). + </para> + </listitem> + </itemizedlist> + + <para> + <command>mailmessage_tree_new()</command> will initialize a + message node. + </para> + + <para> + <command>mailmessage_tree_free()</command> will release + memory used by the node. This will <emphasis>NOT</emphasis> + free the message. + </para> + </sect2> + + <sect2 id="mail-flags"> + <title>Message flags</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +enum { + MAIL_FLAG_NEW = 1 << 0, + MAIL_FLAG_SEEN = 1 << 1, + MAIL_FLAG_FLAGGED = 1 << 2, + MAIL_FLAG_DELETED = 1 << 3, + MAIL_FLAG_ANSWERED = 1 << 4, + MAIL_FLAG_FORWARDED = 1 << 5, + MAIL_FLAG_CANCELLED = 1 << 6, +}; + +struct mail_flags { + uint32_t fl_flags; + clist * fl_extension; /* elements are (char *) */ +}; + +struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_ext); + +void mail_flags_free(struct mail_flags * flags); + +int mail_flags_add_extension(struct mail_flags * flags, + char * ext_flag); + +int mail_flags_remove_extension(struct mail_flags * flags, + char * ext_flag); + +int mail_flags_has_extension(struct mail_flags * flags, + char * ext_flag); + </programlisting> + + <para> + This is the structure containing the message flags. + </para> + + <itemizedlist> + <listitem> + <para> + <command>fl_flags</command> will contain the standards + flags. The value will be a combinaison (with or binary + operation) of <command>MAIL_FLAG_XXX</command> values. + </para> + </listitem> + <listitem> + <para> + <command>fl_extension</command> will be a list (see + <xref linkend="clist">) of strings representing the + non-standard flags. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Example</title> + + <example> + <title>use of message</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +#define DEST_CHARSET "iso-8859-1" + +enum { + NO_ERROR, + ERROR_FILE, + ERROR_MEMORY, + ERROR_INVAL, + ERROR_FETCH, +}; + +/* returns TRUE is given MIME part is a text part */ + +int etpan_mime_is_text(struct mailmime * build_info) +{ + if (build_info->mm_type == MAILMIME_SINGLE) { + if (build_info->mm_content_type != NULL) { + if (build_info->mm_content_type->ct_type->tp_type == + MAILMIME_TYPE_DISCRETE_TYPE) { + if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type == + MAILMIME_DISCRETE_TYPE_TEXT) + return 1; + } + } + else + return 1; + } + + return 0; +} + + +/* display content type */ + +int show_part_info(FILE * f, + struct mailmime_single_fields * mime_fields, + struct mailmime_content * content) +{ + char * description; + char * filename; + int col; + int r; + + description = mime_fields->fld_description; + filename = mime_fields->fld_disposition_filename; + + col = 0; + + r = fprintf(f, " [ Part "); + if (r < 0) + goto err; + + if (content != NULL) { + r = mailmime_content_type_write(f, &col, content); + if (r != MAILIMF_NO_ERROR) + goto err; + } + + if (filename != NULL) { + r = fprintf(f, " (%s)", filename); + if (r < 0) + goto err; + } + + if (description != NULL) { + r = fprintf(f, " : %s", description); + if (r < 0) + goto err; + } + + r = fprintf(f, " ]\n\n"); + if (r < 0) + goto err; + + return NO_ERROR; + + err: + return ERROR_FILE; +} + +/* fetch message and decode if it is base64 or quoted-printable */ + +int etpan_fetch_message(mailmessage * msg_info, + struct mailmime * mime_part, + struct mailmime_single_fields * fields, + char ** result, size_t * result_len) +{ + char * data; + size_t len; + int r; + int encoding; + char * decoded; + size_t decoded_len; + size_t cur_token; + int res; + int encoded; + + encoded = 0; + + r = mailmessage_fetch_section(msg_info, + mime_part, &data, &len); + if (r != MAIL_NO_ERROR) { + res = ERROR_FETCH; + goto err; + } + + encoded = 1; + + /* decode message */ + + if (encoded) { + if (fields->fld_encoding != NULL) + encoding = fields->fld_encoding->enc_type; + else + encoding = MAILMIME_MECHANISM_8BIT; + } + else { + encoding = MAILMIME_MECHANISM_8BIT; + } + + cur_token = 0; + r = mailmime_part_parse(data, len, &cur_token, + encoding, &decoded, &decoded_len); + if (r != MAILIMF_NO_ERROR) { + res = ERROR_FETCH; + goto free; + } + + mailmessage_fetch_result_free(msg_info, data); + + * result = decoded; + * result_len = decoded_len; + + return NO_ERROR; + + free: + mailmessage_fetch_result_free(msg_info, data); + err: + return res; +} + +/* fetch fields */ + +struct mailimf_fields * fetch_fields(mailmessage * msg_info, + struct mailmime * mime) +{ + char * data; + size_t len; + int r; + size_t cur_token; + struct mailimf_fields * fields; + + r = mailmessage_fetch_section_header(msg_info, mime, + &data, &len); + if (r != MAIL_NO_ERROR) + return NULL; + + cur_token = 0; + r = mailimf_envelopes_fields_parse(data, len, + &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + mailmessage_fetch_result_free(msg_info, data); + return NULL; + } + + mailmessage_fetch_result_free(msg_info, data); + + return fields; +} + +/* render message */ + +static int etpan_render_mime(FILE * f, mailmessage * msg_info, + struct mailmime * mime) +{ + int r; + clistiter * cur; + int col; + int text; + int show; + struct mailmime_single_fields fields; + int res; + + mailmime_single_fields_init(&fields, mime->mm_mime_fields, + mime->mm_content_type); + + text = etpan_mime_is_text(mime); + + r = show_part_info(f, &fields, mime->mm_content_type); + if (r != NO_ERROR) { + res = r; + goto err; + } + + switch(mime->mm_type) { + case MAILMIME_SINGLE: + show = 0; + if (text) + show = 1; + + if (show) { + char * data; + size_t len; + char * converted; + size_t converted_len; + char * source_charset; + size_t write_len; + + /* viewable part */ + + r = etpan_fetch_message(msg_info, mime, + &fields, &data, &len); + if (r != NO_ERROR) { + res = r; + goto err; + } + + source_charset = fields.fld_content_charset; + if (source_charset == NULL) + source_charset = DEST_CHARSET; + + r = charconv_buffer(source_charset, DEST_CHARSET, + data, len, &converted, &converted_len); + if (r != MAIL_CHARCONV_NO_ERROR) { + + r = fprintf(f, "[ error converting charset from %s to %s ]\n", + source_charset, DEST_CHARSET); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + + write_len = fwrite(data, 1, len, f); + if (write_len != len) { + mailmime_decoded_part_free(data); + res = r; + goto err; + } + } + else { + write_len = fwrite(converted, 1, converted_len, f); + if (write_len != len) { + charconv_buffer_free(converted); + mailmime_decoded_part_free(data); + res = r; + goto err; + } + + charconv_buffer_free(converted); + } + + write_len = fwrite("\r\n\r\n", 1, 4, f); + if (write_len < 4) { + mailmime_decoded_part_free(data); + res = ERROR_FILE; + goto err; + } + + mailmime_decoded_part_free(data); + } + else { + /* not viewable part */ + + r = fprintf(f, " (not shown)\n\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + break; + + case MAILMIME_MULTIPLE: + + if (strcasecmp(mime->mm_content_type->ct_subtype, + "alternative") == 0) { + struct mailmime * prefered_body; + int prefered_score; + + /* case of multiple/alternative */ + + /* + we choose the better part, + alternative preference : + + text/plain => score 3 + text/xxx => score 2 + other => score 1 + */ + + prefered_body = NULL; + prefered_score = 0; + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * submime; + int score; + + score = 1; + submime = clist_content(cur); + if (etpan_mime_is_text(submime)) + score = 2; + + if (submime->mm_content_type != NULL) { + if (strcasecmp(submime->mm_content_type->ct_subtype, + "plain") == 0) + score = 3; + } + + if (score > prefered_score) { + prefered_score = score; + prefered_body = submime; + } + } + + if (prefered_body != NULL) { + r = etpan_render_mime(f, msg_info, prefered_body); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + else { + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + + r = etpan_render_mime(f, msg_info, clist_content(cur)); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + + break; + + case MAILMIME_MESSAGE: + + if (mime->mm_data.mm_message.mm_fields != NULL) { + struct mailimf_fields * fields; + + if (msg_info != NULL) { + fields = fetch_fields(msg_info, mime); + if (fields == NULL) { + res = ERROR_FETCH; + goto err; + } + + col = 0; + r = mailimf_fields_write(f, &col, fields); + if (r != NO_ERROR) { + mailimf_fields_free(fields); + res = r; + goto err; + } + + mailimf_fields_free(fields); + } + else { + col = 0; + r = fields_write(f, &col, mime->mm_data.mm_message.mm_fields); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + r = fprintf(f, "\r\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + r = etpan_render_mime(f, msg_info, + mime->mm_data.mm_message.mm_msg_mime); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + break; + } + + return NO_ERROR; + + err: + return res; +} + + + +int main(void) +{ + struct mailstorage * storage; + int r; + + storage = mailstorage_new(NULL); + + imap_mailstorage_init(storage, "imap.my-servers.org", 0, + NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN, + "my-login", "my-password", 1, "/home/login/.libetpan/cache"); + + r = mailstorage_connect(storage); + if (r == MAIL_NO_ERROR) { + struct mailfolder * folder; + + folder = mailfolder_new(storage, "INBOX", NULL); + + r = mailfolder_connect(folder); + if (r == MAIL_NO_ERROR) { + struct mailmessage_list * msg_list; + mailmessage * msg; + + mailfolder_get_messages_list(folder, &msg_list); + + if (carray_count(msg_list->msg_tab) > 0) { + struct mailmime * mime; + + msg = carray_get(msg_list->msg_tab, 0); + + mailmessage_get_bodystructure(msg, &mime); + + recursive_fetch(msg, mime); + + /* do the things */ + + mailmessage_flush(msg); + } + mailmessage_list_free(msg_list); + + mailfolder_disconnect(folder); + } + + mailstorage_disconnect(storage); + } + + mailstorage_free(storage); +} + </programlisting> + </example> + </sect2> + </sect1> + + <!-- Session --> + <sect1> + <title>Session</title> + + <sect2 id="mailsession-driver"> + <title>Session driver</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailsession_driver { + char * sess_name; + + int (* sess_initialize)(mailsession * session); + void (* sess_uninitialize)(mailsession * session); + + int (* sess_parameters)(mailsession * session, + int id, void * value); + + int (* sess_connect_stream)(mailsession * session, mailstream * s); + int (* sess_connect_path)(mailsession * session, char * path); + + int (* sess_starttls)(mailsession * session); + + int (* sess_login)(mailsession * session, char * userid, char * password); + int (* sess_logout)(mailsession * session); + int (* sess_noop)(mailsession * session); + + /* folders operations */ + + int (* sess_build_folder_name)(mailsession * session, char * mb, + char * name, char ** result); + + int (* sess_create_folder)(mailsession * session, char * mb); + int (* sess_delete_folder)(mailsession * session, char * mb); + int (* sess_rename_folder)(mailsession * session, char * mb, + char * new_name); + int (* sess_check_folder)(mailsession * session); + int (* sess_examine_folder)(mailsession * session, char * mb); + int (* sess_select_folder)(mailsession * session, char * mb); + int (* sess_expunge_folder)(mailsession * session); + int (* sess_status_folder)(mailsession * session, char * mb, + uint32_t * result_num, uint32_t * result_recent, + uint32_t * result_unseen); + int (* sess_messages_number)(mailsession * session, char * mb, + uint32_t * result); + int (* sess_recent_number)(mailsession * session, char * mb, + uint32_t * result); + int (* sess_unseen_number)(mailsession * session, char * mb, + uint32_t * result); + + int (* sess_list_folders)(mailsession * session, char * mb, + struct mail_list ** result); + int (* sess_lsub_folders)(mailsession * session, char * mb, + struct mail_list ** result); + + int (* sess_subscribe_folder)(mailsession * session, char * mb); + int (* sess_unsubscribe_folder)(mailsession * session, char * mb); + + /* messages operations */ + + int (* sess_append_message)(mailsession * session, + char * message, size_t size); + int (* sess_copy_message)(mailsession * session, + uint32_t num, char * mb); + int (* sess_move_message)(mailsession * session, + uint32_t num, char * mb); + + int (* sess_get_message)(mailsession * session, + uint32_t num, mailmessage ** result); + + int (* sess_get_message_by_uid)(mailsession * session, + const char * uid, mailmessage ** result); + + int (* sess_get_messages_list)(mailsession * session, + struct mailmessage_list ** result); + int (* sess_get_envelopes_list)(mailsession * session, + struct mailmessage_list * env_list); + int (* sess_remove_message)(mailsession * session, uint32_t num); +}; + </programlisting> + + <para> + This is a driver for a session. + </para> + + <itemizedlist> + <listitem> + <para> + <command>sess_name</command> is the name of the driver. + </para> + </listitem> + + <listitem> + <para> + <command>sess_initialize()</command> is the function + that will initializes a data structure (field + <command>sess_data</command> in the session) specific to + the driver. + The field data (field <command>sess_data</command> in + the session) is the state of the session, + the internal data structure used by the driver. + It is called when creating the + <command>mailsession</command> structure with + <command>mailsession_new()</command>. + </para> + </listitem> + + <listitem> + <para> + <command>sess_uninitialize()</command> frees the structure + created with <command>sess_initialize()</command> + </para> + </listitem> + + <listitem> + <para> + <command>sess_parameters()</command> implements + functions specific to the given mail access. + </para> + </listitem> + + <listitem> + <para> + <command>sess_connect_stream()</command> connects a + stream to the session. + </para> + </listitem> + + <listitem> + <para> + <command>sess_connect_path()</command> notify a main + path to the session. + </para> + </listitem> + + <listitem> + <para> + <command>sess_starttls()</command> changes the current + stream to a TLS stream + (see <xref linkend="mailstream-ssl">). + </para> + </listitem> + + <listitem> + <para> + <command>sess_login()</command> notifies the user and + the password to authenticate to the session. + </para> + </listitem> + + <listitem> + <para> + <command>sess_logout()</command> exits the session and + closes the stream. + </para> + </listitem> + + <listitem> + <para> + <command>sess_noop()</command> does no operation on the + session, but it can be used to poll for the status of + the connection. + </para> + </listitem> + + <listitem> + <para> + <command>sess_build_folder_name()</command> will return an + allocated string with that contains the complete path of + the folder to create. + <emphasis>Use of this method is deprecated</emphasis>. + </para> + </listitem> + + <listitem> + <para> + <command>sess_create_folder()</command> creates the + folder that corresponds to the given name. + <emphasis>Use of this method is deprecated</emphasis>. + </para> + </listitem> + + <listitem> + <para> + <command>sess_delete_folder()</command> deletes the folder + that corresponds to the given name. + <emphasis>Use of this method is deprecated</emphasis>. + </para> + </listitem> + + <listitem> + <para> + <command>sess_rename_folder()</command> change the name + of the folder. + <emphasis>Use of this method is deprecated</emphasis>. + </para> + </listitem> + + <listitem> + <para> + <command>sess_check_folder()</command> makes a + checkpoint of the session. + </para> + </listitem> + + <listitem> + <para> + <command>sess_examine_folder()</command> selects a mailbox as + readonly. + <emphasis>Use of this method is deprecated</emphasis>. + </para> + </listitem> + + <listitem> + <para> + <command>sess_select_folder()</command> selects a mailbox. + </para> + </listitem> + + <listitem> + <para> + <command>sess_expunge_folder()</command> deletes all + messages marked \Deleted. + </para> + </listitem> + + <listitem> + <para> + <command>sess_status_folder()</command> queries the + status of the folder (number of messages, number of + recent messages, number of unseen messages). + </para> + </listitem> + + <listitem> + <para> + <command>sess_messages_number()</command> queries the + number of messages in the folder. + </para> + </listitem> + + <listitem> + <para> + <command>sess_recent_number()</command> queries the + number of recent messages in the folder. + </para> + </listitem> + + <listitem> + <para> + <command>sess_unseen_number()</command> queries the number of + unseen messages in the folder. + </para> + </listitem> + + <listitem> + <para> + <command>sess_list_folders()</command> returns the list of + all sub-mailboxes of the given mailbox. + <emphasis>Use of this method is deprecated</emphasis>. + </para> + </listitem> + + <listitem> + <para> + <command>sess_lsub_folders()</command> returns the list of + subscribed sub-mailboxes of the given mailbox. + <emphasis>Use of this method is deprecated</emphasis>. + </para> + </listitem> + + <listitem> + <para> + <command>sess_subscribe_folder()</command> subscribes to + the given mailbox. + <emphasis>Use of this method is deprecated</emphasis>. + </para> + </listitem> + + <listitem> + <para> + <command>sess_unsubscribe_folder()</command> unsubscribes to + the given mailbox. + <emphasis>Use of this method is deprecated</emphasis>. + </para> + </listitem> + + <listitem> + <para> + <command>sess_append_message()</command> adds a RFC 2822 + message to the current given mailbox. + </para> + </listitem> + + <listitem> + <para> + <command>sess_copy_message()</command> copies a message + whose number is given to a given mailbox. The mailbox + must be accessible from the same session. + <emphasis>Use of this method is deprecated</emphasis>. + </listitem> + + <listitem> + <para> + <command>sess_move_message()</command> moves a message whose + number is given to + a given mailbox. The mailbox must be accessible from the + same session. + <emphasis>Use of this method is deprecated</emphasis>. + </para> + </listitem> + + <listitem> + <para> + <command>sess_get_messages_list()</command> returns the list + of message numbers + of the current mailbox + (see <xref linkend="mailmessage-list">). + </para> + </listitem> + + <listitem> + <para> + <command>sess_get_envelopes_list()</command> fills the parsed + fields in the <command>mailmessage</command> structures + (see <xref linkend="mailmessage">) + of the <command>mailmessage_list</command> + (see <xref linkend="mailmessage-list">). + </para> + </listitem> + + <listitem> + <para> + <command>sess_remove_message()</command> removes the given + message from the mailbox. + The message is permanently deleted. + <emphasis>Use of this method is deprecated</emphasis>. + </para> + </listitem> + + <listitem> + <para> + <command>sess_get_message()</command> returns a + mailmessage structure + (see <xref linkend="mailmessage">) + that corresponds + to the given message number. + <emphasis>Use of this method is deprecated</emphasis>. + </para> + </listitem> + + <listitem> + <para> + <command>sess_get_message_by_uid()</command> returns a + mailmessage structure + (see <xref linkend="mailmessage">) + that corresponds + to the given message unique identifier. + </para> + </listitem> + </itemizedlist> + + <para> + mandatory functions are the following : + </para> + + <itemizedlist> + <listitem> + <para> + <command>sess_connect_stream()</command> or + <command>connect_path()</command> + </para> + </listitem> + + <listitem> + <para> + <command>sess_logout()</command> + </para> + </listitem> + + <listitem> + <para> + <command>sess_get_messages_list()</command> + </para> + </listitem> + + <listitem> + <para> + <command>sess_get_envelopes_list()</command> + </para> + </listitem> + </itemizedlist> + + <para> + we advise you to implement these functions : + </para> + + <itemizedlist> + <listitem> + <para> + <command>sess_select_folder()</command> (in case a session + can access several folders). + </para> + </listitem> + + <listitem> + <para> + <command>sess_noop()</command> (to check if the server is + responding) + </para> + </listitem> + + <listitem> + <para> + <command>sess_check_folder()</command> (to make a checkpoint + of the session) + </para> + </listitem> + + <listitem> + <para> + <command>sess_status_folder()</command>, + <command>sess_messages_number()</command>, + <command>sess_recent_number()</command>, + <command>sess_unseen_number()</command> + (to get stat of the folder) + </para> + </listitem> + + <listitem> + <para> + <command>sess_append_message()</command> (but can't be done + in the case of POP3 at least). + </para> + </listitem> + + <listitem> + <para> + <command>sess_login()</command> in a case of an + authenticated driver. + </para> + </listitem> + + <listitem> + <para> + <command>sess_starttls()</command> in a case of a stream + driver, if the procotol supports STARTTLS. + </para> + </listitem> + + <listitem> + <para> + <command>sess_get_message_by_uid()</command> so that the + application can remember the messages + by UID and build its own list of messages. + </para> + </listitem> + + <listitem> + <para> + Everything that is specific to the driver will be + implemented in <command>sess_parameters()</command>. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2 id="mailsession"> + <title>Session</title> + + <programlisting role="C"> +#include <libetpan/libetpan.h> + +struct mailsession { + void * sess_data; + mailsession_driver * sess_driver; +}; + +mailsession * mailsession_new(mailsession_driver * sess_driver); + +void mailsession_free(mailsession * session); + </programlisting> + + <para> + This is a session. This is an abstraction used to access the + storage, using the network or the filesystem. + </para> + + <itemizedlist> + <listitem> + <para> + <command>sess_data</command> is the state of the + session. This is specific to the driver. + </para> + </listitem> + <listitem> + <para> + <command>sess_driver</command> is the driver of the + session. + </para> + </listitem> + </itemizedlist> + + <para> + <command>mailsession_new()</command> will create a new session + using the given driver (<command>sess_driver</command>). + </para> + + <para> + <command>mailsession_free()</command> will release the memory + used by the session. + </para> + </sect2> + + <sect2> + <title>mailsession_parameters</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_parameters(mailsession * session, + int id, void * value); + </programlisting> + + <para> + This function make calls specific to the driver + </para> + </sect2> + + <sect2> + <title>mailsession_connect_stream</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_connect_stream(mailsession * session, mailstream * s); + </programlisting> + + <para> + There are drivers of two kinds : stream drivers (driver that + connects to servers through TCP or other means of connection) + and file drivers (driver that are based on filesystem) + + This function can only be used by stream drivers and + this connects a stream to the session + </para> + </sect2> + + <sect2> + <title>mailsession_connect_path</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_connect_path(mailsession * session, char * path); + </programlisting> + + <para> + This function can only be used by file drivers and + selects the main path of the session. + </para> + </sect2> + + <sect2> + <title>mailsession_starttls</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_starttls(mailsession * session); + </programlisting> + + <para> + This switches the current connection to TLS (secure layer). + This will only work with stream drivers. + </para> + </sect2> + + <sect2> + <title>mailsession_login</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_login(mailsession * session, + char * userid, char * password); + </programlisting> + + <para> + This notifies the login and the password to authenticate + to the session. + </para> + </sect2> + + <sect2> + <title>mailsession_logout</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_logout(mailsession * session); + </programlisting> + + <para> + This function disconnects the session and closes the stream. + </para> + </sect2> + + <sect2> + <title>mailsession_noop</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_noop(mailsession * session); + </programlisting> + + <para> + This function does no operation on the session, but it can be + used to poll for the status of the connection. + </para> + </sect2> + + <sect2> + <title>mailsession_check_folder</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_check_folder(mailsession * session); + </programlisting> + + <para> + This function makes a checkpoint of the session. + </para> + </sect2> + + <sect2> + <title>mailsession_select_folder</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_select_folder(mailsession * session, char * mb); + </programlisting> + + <para> + This function selects a mailbox. + </para> + </sect2> + + <sect2> + <title>mailsession_expunge_folder</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_expunge_folder(mailsession * session); + </programlisting> + + <para> + This function deletes all messages marked for deletion. + </para> + </sect2> + + <sect2> + <title>mailsession_status_folder</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + </programlisting> + + <para> + This function queries the status of the folder + (number of messages, number of recent messages, number of + unseen messages). + </para> + </sect2> + + <sect2> + <title>mailsession_messages_number</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_messages_number(mailsession * session, char * mb, + uint32_t * result); + </programlisting> + + <para> + This function queries the number of messages in the folder. + </para> + </sect2> + + <sect2> + <title>mailsession_recent_number</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_recent_number(mailsession * session, + char * mb, uint32_t * result); + </programlisting> + + <para> + This function queries the number of recent messages in the + folder. + </para> + </sect2> + + <sect2> + <title>mailsession_unseen_number</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_unseen_number(mailsession * session, char * mb, + uint32_t * result); + </programlisting> + + <para> + This function queries the number of unseen messages in the + folder. + </para> + </sect2> + + <sect2> + <title>mailsession_append_message</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_append_message(mailsession * session, + char * message, size_t size); + </programlisting> + + <para> + This adds a RFC 2822 message to the current mailbox. + </para> + </sect2> + + <sect2> + <title>mailsession_get_messages_list</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + </programlisting> + + <para> + This function returns the list of messages + of the current mailbox. + </para> + </sect2> + + <sect2> + <title>mailsession_get_envelopes_list</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_get_envelopes_list(mailsession * session, + struct mailmessage_list * result); + </programlisting> + + <para> + This function fills the parsed fields in the + <command>mailmessage</command> structures + (see <xref linkend="mailmessage">) + of the mailmessage_list + (see <xref linkend="mailmessage-list">). + </para> + </sect2> + + <sect2> + <title>mailsession_get_message</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + </programlisting> + + <para> + This function returns a <command>mailmessage</command> + (see <xref linkend="mailmessage">) structure that + corresponds to the given message number. + </para> + + <warning> + <para> + <command>mailsession_get_message_by_uid()</command> should + be used instead. + </para> + </warning> + </sect2> + + <sect2> + <title>mailsession_get_message_by_uid</title> + + <programlisting> +#include <libetpan/libetpan.h> + +int mailsession_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + </programlisting> + + <para> + This function returns a mailmessage structure + that corresponds to the given message unique identifier. + This is currently implemented only for cached drivers. + </para> + <warning> + <para> + That deprecates the use of + <command>mailsession_get_message()</command>. + </para> + </warning> + </sect2> + </sect1> + </chapter> + +</book> Added: freeswitch/trunk/libs/libetpan/doc/API.txt ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API.txt Wed Dec 20 15:28:56 2006 @@ -0,0 +1,10978 @@ + +libEtPan! API + +Viet Hoa DINH + + Copyright � 2003 DINH Viet Hoa + _________________________________________________________________ + + Table of Contents + 1. Introduction + 2. Tools and datatypes + + Array + + carray_new and carray_free + carray_set_size + carray_count, carray_add, carray_get and carray_set + carray_delete + carray_data + + List + + clist_new and clist_free + clist_isempty and clist_count + running through clist + clist modification + clist_foreach + clist_concat + + Hash table + + chash_new and chash_free + chash_set and chash_get + chash_delete + chash_resize + running through the chash + chash_size and chash_count + + Buffered I/O + + socket stream + TLS stream + + non-buffered I/O + strings + + constructor and destructor + string value modification + insertion in string, deletion in string + referencing string + + 3. Internet Message Format + + Quick start + + Parse message headers + Render the message headers + + Data types + + mailimf_mailbox - mailbox + mailimf_address - address + mailimf_mailbox_list - list of mailboxes + mailimf_address_list - list of addresses + mailimf_group - named group of mailboxes + mailimf_date_time - date of a message + mailimf_orig_date - parsed content of date header + mailimf_from - parsed content of From header + mailimf_sender - parsed content of Sender header + mailimf_reply_to - parsed content of Reply-To header + mailimf_to - parsed content of To header + mailimf_cc - parsed content of Cc + mailimf_bcc - parsed content of Bcc field + mailimf_message_id - parsed content of Message-ID header + mailimf_in_reply_to - parsed content of In-Reply-To field + mailimf_references - parsed content of References field + mailimf_subject - parsed content of Subject field + mailimf_comments - parsed content of Comments field + mailimf_keywords - parsed content of Keywords field + mailimf_return - parsed content of Return-Path field + mailimf_path - address in Return-Path field + mailimf_optional_field - non-standard header + mailimf_field - header field + mailimf_fields - list of header fields + mailimf_body - message body without headers + mailimf_message - parsed message + mailimf_single_fields - simplified fields + + Parser functions + + mailimf_address_list_parse + mailimf_address_parse + mailimf_body_parse + mailimf_envelope_and_optional_fields_parse + mailimf_envelope_fields_parse + mailimf_optional_fields_parse + mailimf_fields_parse + mailimf_ignore_field_parse + mailimf_mailbox_list_parse + mailimf_mailbox_parse + mailimf_message_parse + + Creation functions + + mailimf_mailbox_list + mailimf_address_list + mailimf_fields + + Rendering of messages + + Header fields + + 4. MIME + + Quick start + + Parse MIME message + Render the MIME message + + Data types + + mailmime_composite_type - Composite MIME type + mailmime_content - MIME content type (Content-Type) + mailmime_discrete_type - MIME discrete type + mailmime_field - MIME header field + mailmime_mechanism - MIME transfer encoding mechanism + (Content-Transfer-Encoding) + + mailmime_fields - header fields + mailmime_parameter - MIME type parameter + mailmime_type - MIME main type + mailmime_language - Language of MIME part + mailmime_data - Content of MIME part + mailmime - MIME part + mailmime_disposition - MIME disposition information + (Content-Disposition) + + mailmime_disposition_type - Type of MIME disposition + mailmime_disposition_parm - MIME disposition parameter + mailmime_single_fields - MIME headers + + Parser functions + + mailmime_content_parse + mailmime_description_parse + mailmime_encoding_parse + mailmime_field_parse + mailmime_id_parse + mailmime_fields_parse + mailmime_version_parse + mailmime_parameter_parse + mailmime_language_parse + mailmime_disposition_parse + mailmime_disposition_type_parse + mailmime_encoded_phrase_parse + mailmime_parse + mailmime_base64_body_parse + mailmime_quoted_printable_body_parse + mailmime_binary_body_parse + mailmime_part_parse + + Rendering of MIME parts + + mailmime_fields_write, mailmime_content_write and + mailmime_content_type_write + + mailmime_write + mailmime_quoted_printable_write and mailmime_base64_write + mailmime_data_write + + Creation functions + + mailmime_disposition_new_filename and + mailmime_disposition_new_with_data + + mailmime_fields_new_empty and mailmime_fields_add + mailmime_fields_new_with_data and + mailmime_fields_new_with_version + + mailmime_get_content_message + mailmime_data_new_data and mailmime_data_new_file + mailmime_new_message_data, mailmime_new_empty and + mailmime_new_with_content + + mailmime_set_preamble_file, mailmime_set_epilogue_file, + mailmime_set_preamble_text and + mailmime_set_epilogue_text + + mailmime_set_body_file and mailmime_set_body_text + mailmime_add_part, mailmime_remove_part, + mailmime_smart_add_part and + mailmime_smart_remove_part + + mailmime_set_imf_fields + mailmime_fields_new_encoding and + mailmime_fields_new_filename + + Helper functions + + mailmime_transfer_encoding_get + mailmime_content_charset_get and mailmime_content_param_get + + 5. Storages, folders, messages + + Introduction + + Message + MIME part + Mailbox + Storage + Folder + Session + + Error codes + Storage + + Storage driver + Storage + mailstorage_new and mailstorage_free + mailstorage_connect and mailstorage_disconnect + IMAP storage + Example + + Folder + + Folder driver + Folder + mailfolder_new and mail_folder_free + mailfolder_connect and mailfolder_disconnect + mailfolder_noop + mailfolder_check + mailfolder_expunge + mailfolder_status + mailfolder_append_message + mailfolder_get_messages_list + mailfolder_get_envelopes_list + mailfolder_get_message + mailfolder_get_message_by_uid + Example + + Message + + Message driver + Message + mailmessage_new + mailmessage_init + mailmessage_flush + mailmessage_check + mailmessage_fetch_result_free + mailmessage_fetch + mailmessage_fetch_header + mailmessage_fetch_body + mailmessage_fetch_size + mailmessage_get_bodystructure + mailmessage_fetch_section + mailmessage_fetch_section_header + mailmessage_fetch_section_mime + mailmessage_fetch_section_body + mailmessage_fetch_envelope + mailmessage_get_flags + mailmessage_resolve_single_fields + Message list + Message tree + Message flags + Example + + Session + + Session driver + Session + mailsession_parameters + mailsession_connect_stream + mailsession_connect_path + mailsession_starttls + mailsession_login + mailsession_logout + mailsession_noop + mailsession_check_folder + mailsession_select_folder + mailsession_expunge_folder + mailsession_status_folder + mailsession_messages_number + mailsession_recent_number + mailsession_unseen_number + mailsession_append_message + mailsession_get_messages_list + mailsession_get_envelopes_list + mailsession_get_message + mailsession_get_message_by_uid + + List of Examples + 2-1. carray creation + 2-2. preallocating carray + 2-3. carray access + 2-4. deletion in carray + 2-5. clist creation + 2-6. displaying content of clist + 2-7. deleting elements in a clist + 2-8. merging two clists + 2-9. chash insert and lookup + 2-10. key deletion in a chash + 2-11. running through a chash + 3-1. example of mailbox + 3-2. mailbox creation and display + 3-3. address creation and display + 3-4. Creation and display of mailimf_mailbox_list + 3-5. creation and display of list of addresses + 3-6. example of group + 3-7. creation and display of a group + 3-8. example of date + 3-9. creation and display of date + 3-10. creation and display of Date field + 3-11. creation and display of a From header + 3-12. creation and display of Sender field + 3-13. creation and display of Reply-To field + 3-14. creation and display of To field + 3-15. creation and display of Cc field + 3-16. creation and display of Bcc field + 3-17. example of Message-ID + 3-18. creation and display of Message-ID field + 3-19. creation and display of In-Reply-To field + 3-20. creation and display of References field + 3-21. creation and display of Subject field + 3-22. creation and display of Comment field + 3-23. creation and display of Keywords field + 3-24. creation and display of Return-Path field + 3-25. Creation and display of return path + 3-26. creation and display of non-standard fields + 3-27. creation and display of field + 3-28. creation and display of header fields + 3-29. creation and display of message body + 3-30. creation and display of message + 3-31. using mailimf_single_fields + 3-32. using mailimf_single_fields without memory allocation + 3-33. parsing a list of addresses + 3-34. parsing an address + 3-35. parsing a message body + 3-36. parsing commonly used fields and return other fields in a + non-parsed form + + 3-37. parsing commonly used fields + 3-38. parsing optional fields + 3-39. parsing header fields + 3-40. skipping fields + 3-41. parsing a list of mailboxes + 3-42. parsing a mailbox + 3-43. parsing a message + 3-44. creating a list of mailboxes + 3-45. creation of header fields + 3-46. rendering of fields + 4-1. create and display MIME composite type + 4-2. Creation and display of MIME content type + 4-3. Creation and display of MIME discrete type + 4-4. Creation and display of MIME header field + 4-5. Creation and display of MIME transfer encoding mechanism + 4-6. Creation and display of MIME fields + 4-7. Creation and display of MIME type parameter + 4-8. Creation and display of MIME main type + 4-9. Creation and display of language of MIME part + 4-10. Creation and display of MIME part content + 4-11. Creation and display of MIME part + 4-12. Creation and display of MIME disposition information + 4-13. Creation and display of MIME disposition type + 4-14. Creation and display of MIME disposition parameter + 4-15. Creation and display of single fields + 4-16. Parsing MIME content type + 4-17. Parsing MIME description + 4-18. parsing MIME encoding mechanism + 4-19. parsing MIME header field + 4-20. Parsing MIME content identifier + 4-21. parsing MIME header fields + 4-22. parsing MIME version + 4-23. parsing a MIME parameter + 4-24. Parsing the MIME content langage + 4-25. Parsing the MIME content disposition + 4-26. parsing a MIME content disposition type + 4-27. decoding a MIME encoded header string + 4-28. parsing a MIME message + 4-29. Parsing a base64 encoded part + 4-30. Parsing a quoted printable encoded part + 4-31. Parsing a binary encoded part + 4-32. Parsing a MIME encoded part + 4-33. rendering MIME header fields + 4-34. render base64 or quoted printable + 4-35. creating a MIME content disposition + 4-36. creating a MIME header fields list + 4-37. creating new fields + 4-38. Creating a MIME content type + 4-39. creating MIME content + 4-40. creating a MIME part + 4-41. setting preamble and epilogue + 4-42. creating a MIME part + 4-43. modifying MIME structure + 4-44. modifying MIME structure + 4-45. creating MIME fields with only Content-Transfer-Encoding + 4-46. extracting MIME encoding mechanism + 4-47. extracting information from MIME content type + 5-1. use of storage + 5-2. use of folder + 5-3. use of message + _________________________________________________________________ + +Chapter 1. Introduction + + This document will describe the API of libEtPan! + _________________________________________________________________ + +Chapter 2. Tools and datatypes + + libEtPan! include a collection of datatypes such as lists, arrays, + hash tables and tools such as buffered I/O. + _________________________________________________________________ + +Array + +#include <libetpan/libetpan.h> + +typedef struct carray_s carray; + + + carray is an array of pointers that will resize automatically in case + a new element is added. + + The carray is implemented with an array (void **) that can be resized. + An array has a size: this is the number of elements that can be added + before the table is resized. It also has a count of elements: this is + the elements that exist in the array. + _________________________________________________________________ + +carray_new and carray_free + +carray * carray_new(unsigned int initsize); + +void carray_free(carray * array); + + + carray_new() creates a new array with an initial size. The array is + not resized until the number of element reach the initial size. It + returns NULL in case of failure. + + carray_free() releases memory used by the given array. + + Example 2-1. carray creation +#include <libetpan/libetpan.h> +#include <stdlib.h> + +#define SIZE 50 + +int main(void) +{ + carray * a; + + a = carray_new(SIZE); + if (a == NULL) + exit(EXIT_FAILURE); + + /* do things here */ + + carray_free(a); + + exit(EXIT_SUCESS); +} + + _________________________________________________________________ + +carray_set_size + +int carray_set_size(carray * array, uint32_t new_size); + + + carray_set_size() sets the size of the array. It returns 0 in case of + success, -1 in case of failure. + + Example 2-2. preallocating carray +#include <libetpan/libetpan.h> +#include <stdlib.h> + +#define SIZE 50 +#define NEWSIZE 200 + +int main(void) +{ + carray * a; + unsigned int i; + char p[500]; + + a = carray_new(SIZE); + if (a == NULL) + goto err; + + r = carray_set_size(NEWSIZE); + if (r < 0) + goto free; + + for(i = 0 ; i < NEWSIZE ; i ++) + carray_set(a, i, &p[i]); + + /* do things here */ + + carray_free(a); + + exit(EXIT_SUCESS); + + free: + carray_free(a); + err: + exit(EXIT_FAILURE); +} + + _________________________________________________________________ + +carray_count, carray_add, carray_get and carray_set + +int carray_count(carray); + +int carray_add(carray * array, void * data, unsigned int * index); + +void * carray_get(carray * array, unsigned int indx); + +void carray_set(carray * array, unsigned int indx, void * value); + + + carray_count() returns the number of elements in the carray. + Complexity is O(1). + + carray_add()adds an element at the end of the array. The index of the + element is returns in (* index) if index is not NULL. It returns 0 in + case of success, -1 in case of failure. Complexity is O(1). + + carray_get() returns the elements contained at the given cell of the + table. Complexity is O(1). + + carray_set() replace the element at the given index of table table + with the given value. Complexity is O(1). + + Example 2-3. carray access +#include <libetpan/libetpan.h> +#include <string.h> + +#define SIZE 50 + +int main(void) +{ + carray * a; + int r; + + a = carray_new(SIZE); + if (a == NULL) + goto err; + + r = carray_add(a, "foo-bar-1", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-2", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-3", NULL); + if (r < 0) + goto free; + + for(i = 0 ; i < carray_count(a) ; i ++) { + char * str; + + str = carray_get(a, i); + if (strcmp("foo-bar-2", str) == 0) + carray_set(a, i, "foo-bar-2-replacement"); + + printf("%s\n", str); + } + + carray_free(a); + + exit(EXIT_SUCESS); + + free: + carray_free(a); + err: + exit(EXIT_FAILURE); +} + + _________________________________________________________________ + +carray_delete + +int carray_delete(carray * array, uint32_t indx); + +int carray_delete_slow(carray * array, uint32_t indx); + +int carray_delete_fast(carray * array, uint32_t indx); + + + carray_delete() removes an element of the table. Order will not be + garanteed. The returned result can be ignored. Complexity is O(1). + + carray_delete_slow() removes an element of the table. Order will be + garanteed. The returned result can be ignored. Complexity is O(n). + + carray_delete_fast() the element will just be replaced with NULL. + Order will be kept but the number of elements will remains the same. + The returned result can be ignored. Complexity is O(1). + + Example 2-4. deletion in carray +#include <libetpan/libetpan.h> + +#define SIZE 50 + +carray * build_array(void) +{ + carray * a; + + a = carray_new(SIZE); + if (a == NULL) + goto err; + + r = carray_add(a, "foo-bar-1", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-2", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-3", NULL); + if (r < 0) + goto free; + + return a; + + free: + carray_free(a); + err: + exit(EXIT_FAILURE); +} + +void delete(carray * a) +{ + /* deleting foo-bar-1 */ + carray_delete(a, 0); + /* resulting size is 2, order of elements is undefined */ +} + +void delete_slow(carray * a) +{ + /* deleting foo-bar-1 */ + carray_delete_slow(a, 0); + /* resulting size is 2, order of elements is the same */ +} + +void delete_fast(carray * a) +{ + /* deleting foo-bar-1 */ + carray_delete_slow(a, 0); + /* + resulting size is 3, + order of elements is { NULL, foo-bar-2, foo-bar-3 } + */ +} + + _________________________________________________________________ + +carray_data + +void ** carray_data(carray); + + + carray_datareturns the table used for implementation : (void **). + _________________________________________________________________ + +List + +#include <libetpan/libetpan.h> + +typedef struct clist_s clist; + +typedef clistcell clistiter; + + + clist() is a list of cells. Each cell of the list contains one + element. This element is a pointer. An iterator (clistiter) is a + pointer to an element of the list. With an iterator, we can get the + previous element of the list, the next element of the list and the + content of the element. + _________________________________________________________________ + +clist_new and clist_free + +clist * clist_new(void); + +void clist_free(clist *); + + + clist_new() allocates a new empty list and returns it. + + clist_free() frees the entire list with its cells. + + Example 2-5. clist creation +#include <libetpan/libetpan.h> + +int main(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + goto err; + + r = clist_append(list, "foo-bar"); + if (r < 0) + + clist_free(list); + + exit(EXIT_SUCCESS); + + free: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + + _________________________________________________________________ + +clist_isempty and clist_count + +int clist_isempty(clist *); + +int clist_count(clist *); + + + clist_isempty() returns 1 if the list is empty, else it is 0. + Complexity is O(1). + + clist_count() returns the number of elements in the list. Complexity + is O(1). + _________________________________________________________________ + +running through clist + +clistiter * clist_begin(clist *); + +clistiter * clist_end(clist *); + +clistiter * clist_next(clistiter *); + +clistiter * clist_previous(clistiter *); + +void * clist_content(clistiter *); + +void * clist_nth_data(clist * lst, int index); + +clistiter * clist_nth(clist * lst, int index); + + + clist_begin() returns an iterator to the first element of the list. + Complexity is O(1). + + clist_end() returns an iterator to the last element of the list. + Complexity is O(1). + + clist_next() returns an iterator to the next element of the list. + Complexity is O(1). + + clist_previous() returns an iterator to the previous element of the + list. Complexity is O(1). + + clist_content() returns the element contained in the cell pointed by + the iterator in the list. Complexity is O(1). + + clist_nth() returns an iterator on the index-th element of the list. + Complexity is O(n). + + clist_nth_data() returns the index-th element of the list. Complexity + is O(n). + + Example 2-6. displaying content of clist +#include <libetpan/libetpan.h> + +int main(void) +{ + clist * list; + clistiter * iter; + + list = build_string_list(); + if (list == NULL) + goto err; + + for(iter = clist_begin(list) ; iter != NULL ; iter = + clist_next(iter)) { + char * str; + + str = clist_content(iter); + printf("%s\n", str); + } + + clist_free(list); + + exit(EXIT_SUCCESS); + + free: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + + _________________________________________________________________ + +clist modification + +int clist_prepend(clist *, void *); + +int clist_append(clist *, void *); + +int clist_insert_before(clist *, clistiter *, void *); + +int clist_insert_after(clist *, clistiter *, void *); + +clistiter * clist_delete(clist *, clistiter *); + + + clist_prepend() adds an element at the beginning of the list. Returns + 0 on sucess, -1 on error. Complexity is O(1). + + clist_append() adds an element at the end of the list. Returns 0 on + sucess, -1 on error. Complexity is O(1). + + clist_insert_before() adds an element before the element pointed by + the given iterator in the list. Returns 0 on sucess, -1 on error. + Complexity is O(1). + + clist_insert_after() adds an element after the element pointed by the + given iterator in the list. Returns 0 on sucess, -1 on error. + Complexity is O(1). + + clist_delete() the elements pointed by the given iterator in the list + and returns an iterator to the next element of the list. Complexity is + O(1). + + Example 2-7. deleting elements in a clist +#include <libetpan/libetpan.h> + +voir print_content(void * content, void * user_data) +{ + char * str; + + str = content; + + printf("%s\n", str); +} + +int main(void) +{ + clist * list; + clistiter * iter; + + list = build_string_list(); + if (list == NULL) + goto err; + + iter = = clist_begin(list); + while (iter != NULL) + char * str; + + str = clist_content(iter); + if (strcmp(str, "foo-bar") == 0) + iter = clist_delete(list, cur); + else + iter = clist_next(iter); + } + + clist_foreach(list, print_content, NULL); + printf("\n"); + + clist_free(list); + + exit(EXIT_SUCCESS); + + free: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + + _________________________________________________________________ + +clist_foreach + +typedef void (* clist_func)(void *, void *); + +void clist_foreach(clist * lst, clist_func func, void * data); + + + clist_foreach() apply a fonction to each element of the list. + Complexity is O(n). + _________________________________________________________________ + +clist_concat + +void clist_concat(clist * dest, clist * src); + + + clist_concat() adds all the elements of src at the end of dest. + Elements are added in the same order. src is an empty list when the + operation is finished. Complexity is O(1). + + Example 2-8. merging two clists +#include <libetpan/libetpan.h> + +int main(void) +{ + clist * list; + clist * list_2; + clistiter * iter; + + list = build_string_list(); + if (list == NULL) + goto err; + + list_2 = build_string_list_2(); + if (list == NULL) + goto free_list; + + clist_concat(list, list_2); + clist_free(list_2); + + for(iter = clist_begin(list) ; iter != NULL ; iter = + clist_next(iter)) { + char * str; + + str = clist_content(iter); + printf("%s\n", str); + } + + clist_free(list); + + exit(EXIT_SUCCESS); + + free_list: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + + _________________________________________________________________ + +Hash table + +#include <libetpan/libetpan.h> + +typedef struct chash chash; + +typedef struct chashcell chashiter; + +typedef struct { + char * data; + int len; +} chashdatum; + + + chash is a hash table. chashiter is a pointer to an element of the + hash table. chashdatum is an element to be placed in the hash table as + a key or a value. It consists in data and a corresponding length. + _________________________________________________________________ + +chash_new and chash_free + +#define CHASH_COPYNONE 0 +#define CHASH_COPYKEY 1 +#define CHASH_COPYVALUE 2 +#define CHASH_COPYALL (CHASH_COPYKEY | CHASH_COPYVALUE) + +chash * chash_new(int size, int flags); + +void chash_free(chash * hash); + + + chash_new() returns a new empty hash table or NULL if this failed. + size is the initial size of the table used for implementation. flags + can be a combinaison of CHASH_COPYKEY and CHASH_COPYVALUE. + CHASH_COPYKEY enables copy of key, so that the initial value used for + chash_set() + + chash_free() releases memory used by the hash table. + _________________________________________________________________ + +chash_set and chash_get + +int chash_set(chash * hash, + chashdatum * key, chashdatum * value, chashdatum * oldvalue); + +int chash_get(chash * hash, + chashdatum * key, chashdatum * result); + + + chash_set() adds a new element into the hash table. If a previous + element had the same key, it is returns into oldvalue if oldvalue is + different of NULL. Medium complexity is O(1). + + returns -1 if it fails, 0 on success. + + chash_get()returns the corresponding value of the given key. If there + is no corresponding value, -1 is returned. 0 on success. Medium + complexity is O(1). + + Example 2-9. chash insert and lookup +int main(void) +{ + chash * hash; + int r; + chashdatum key; + chashdatum value; + char * str1 = "my-data"; + char * str2 = "my-data"; + + hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE); + + key.data = "foo"; + key.len = strlen("foo"); + value.data = str1; + value.data = strlen(str1) + 1; + /* + 1 is needed to get the terminal zero in the returned string */ + r = chash_set(hash, &key, &value, NULL); + if (r < 0) + goto free_hash; + + key.data = "bar"; + key.len = strlen("bar"); + value.data = str2; + value.data = strlen(str2) + 1; + if (r < 0) + goto free_hash; + + key.data = "foo"; + key.len = strlen("foo"); + r = chash_get(hash, &key, &value); + if (r < 0) { + printf("element not found\n"); + } + else { + char * str; + + str = value.data; + printf("found : %s", str); + } + + chash_free(hash); + + exit(EXIT_SUCCESS); + + free_hash: + chash_free(hash); + err: + exit(EXIT_FAILURE); +} + + _________________________________________________________________ + +chash_delete + +int chash_delete(chash * hash, + chashdatum * key, chashdatum * oldvalue); + + + deletes the key/value pair given the corresponding key. The value is + returned in old_value. If there is no corresponding value, -1 is + returned. 0 on success. Medium complexity is O(1). + + Example 2-10. key deletion in a chash +int main(void) +{ + chash * hash; + int r; + chashdatum key; + chashdatum value; + char * str1 = "my-data"; + char * str2 = "my-data"; + + hash = build_hash(); + + key.data = "foo"; + key.len = strlen("foo"); + chash_delete(hash, &key, &value); + + /* it will never be possible to lookup "foo" */ + key.data = "foo"; + key.len = strlen("foo"); + r = chash_get(hash, &key, &value); + if (r < 0) { + printf("element not found\n"); + } + else { + char * str; + + str = value.data; + printf("found : %s", str); + } + + chash_free(hash); + + exit(EXIT_SUCCESS); + + free_hash: + chash_free(hash); + err: + exit(EXIT_FAILURE); +} + + _________________________________________________________________ + +chash_resize + +int chash_resize(chash * hash, int size); + + + chash_resize() changes the size of the table used for implementation + of the hash table. returns 0 on success, -1 on failure. + _________________________________________________________________ + +running through the chash + +chashiter * chash_begin(chash * hash); + +chashiter * chash_next(chash * hash, chashiter * iter); + +void chash_key(chashiter * iter, chashdatum * result); + +void chash_value(chashiter iter, chashdatum * result); + + + chash_begin() returns a pointer to the first element of the hash + table. Returns NULL if there is no elements in the hash table. + Complexity is O(n). + + chash_next() returns a pointer to the next element of the hash table. + Returns NULL if there is no next element. Complexity is O(n) but n + calls to chash_next() also has a complexity of O(n). + + chash_key() returns the key of the given element of the hash table. + + chash_value returns the value of the given element of the hash table. + + Example 2-11. running through a chash +int main(void) +{ + chash * hash; + int r; + chashiter * iter; + + hash = build_hash(); + + /* this will display all the values stored in the hash */ + for(iter = chash_begin(hash) ; iter != NULL ; iter = + chash_next(hash, iter)) { + chashdatum key; + chashdatum value; + char * str; + + chash_value(iter, &value); + str = value.data; + printf("%s\n", str); + } + + chash_free(hash); +} + + _________________________________________________________________ + +chash_size and chash_count + +int chash_size(chash * hash); + +int chash_count(chash * hash); + + + chash_size() returns the size of the table used for implementation of + the hash table. Complexity is O(1). + + chash_count() returns the number of elements in the hash table. + Complexity is O(1). + _________________________________________________________________ + +Buffered I/O + + +#include <libetpan/libetpan.h> + +typedef struct _mailstream mailstream; + + + streams are objects where we can read data from and write data to. + They are not seekable. That can be for example a pipe or a network + stream. +mailstream * mailstream_new(mailstream_low * low, size_t buffer_size); + +int mailstream_close(mailstream * s); + + + mailstream_new() creates a new stream stream with the low-level (see + the Section called non-buffered I/O) stream and a given buffer size. + + mailstream_close() closes the stream. This function will be in charge + to free the mailstream_low structure. + +ssize_t mailstream_write(mailstream * s, void * buf, size_t count); + +int mailstream_flush(mailstream * s); + +ssize_t mailstream_read(mailstream * s, void * buf, size_t count); + +ssize_t mailstream_feed_read_buffer(mailstream * s); + + + mailstream_write() writes a buffer to the given stream. This write + operation will be buffered. + + mailstream_flush() will force a write of all buffered data for a given + stream. + + mailstream_read() reads data from the stream to the given buffer. + + mailstream_feed_read_buffer() this function will just fill the buffer + for reading. + +mailstream_low * mailstream_get_low(mailstream * s); + +void mailstream_set_low(mailstream * s, mailstream_low * low); + + + mailstream_get_low() returns the low-level stream of the given stream. + + mailstream_set_low() changes the low-level of the given stream. + Useful, for example, when a stream change from clear stream to SSL + stream. +char * mailstream_read_line(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_append(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line); + +char * mailstream_read_multiline(mailstream * s, size_t size, + MMAPString * stream_buffer, + MMAPString * multiline_buffer, + size_t progr_rate, + progress_function * progr_fun); + + + mailstream_read_line() reads an entire line from the buffer and store + it into the given string. returns NULL on error, the corresponding + array of char is returned otherwise. + + mailstream_read_line_append() reads an entire line from the buffer and + appends it to the given string. returns NULL on error, the array of + char corresponding to the entire buffer is returned otherwise. + + mailstream_read_line_remove_eol() reads an entire line from the buffer + and store it into the given string. All CR LF are removed. returns + NULL on error, the corresponding array of char is returned otherwise. + + mailstream_read_multiline() reads a multiline data (several lines, the + data are ended with a single period '.') from the given stream and + store it into the given multiline buffer (multiline_buffer). + progr_rate should be 0 and progr_fun NULL (deprecated things). + stream_buffer is a buffer used for internal work of the function. size + should be 0 (deprecated things). + +int mailstream_is_end_multiline(char * line); + + + returns 1 if the line is an end of multiline data (a single period + '.', eventually with CR and/or LF). 0 is returned otherwise. + +int mailstream_send_data(mailstream * s, char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun); + + + sends multiline data to the given stream. size is the size of the + data. progr_rate and progr_fun are deprecated. progr_rate must be 0, + progr_fun must be NULL. + _________________________________________________________________ + +socket stream + +mailstream * mailstream_socket_open(int fd); + + + mailstream_socket_open() will open a clear-text socket. + _________________________________________________________________ + +TLS stream + +mailstream * mailstream_ssl_open(int fd); + + + mailstream_ssl_open() will open a TLS/SSL socket. + _________________________________________________________________ + +non-buffered I/O + + +#include <libetpan/libetpan.h> + +struct mailstream_low_driver { + ssize_t (* mailstream_read)(mailstream_low *, void *, size_t); + ssize_t (* mailstream_write)(mailstream_low *, void *, size_t); + int (* mailstream_close)(mailstream_low *); + int (* mailstream_get_fd)(mailstream_low *); + void (* mailstream_free)(mailstream_low *); +}; + +typedef struct mailstream_low_driver mailstream_low_driver; + +struct _mailstream_low { + void * data; + mailstream_low_driver * driver; +}; + + + mailstream_low is a non-buffered stream. + + The mailstream_low_driver is a set of functions used to access the + stream. + + * mailstream_read/write/close() is the same interface as + read/write/close() system calls, except that the file descriptor + is replaced with the mailstream_low structure. + * mailstream_get_fd() returns the file descriptor used for this + non-buffered stream. + * mailstream_free() is in charge to free the internal structure of + the mailstream_low and the mailstream_low itself. + + +mailstream_low * mailstream_low_new(void * data, + mailstream_low_driver * driver); + + + mailstream_low_new() creates a low-level mailstream with the given + internal structure (data) and using the given set of functions + (driver). + +ssize_t mailstream_low_write(mailstream_low * s, void * buf, size_t count); + +ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count); + +int mailstream_low_close(mailstream_low * s); + +int mailstream_low_get_fd(mailstream_low * s); + +void mailstream_low_free(mailstream_low * s); + + + Each of these calls will call the corresponding function defined in + the driver. + _________________________________________________________________ + +strings + + +#include <libetpan/libetpan.h> + +struct _MMAPString +{ + char * str; + size_t len; + size_t allocated_len; + int fd; + size_t mmapped_size; +}; + +typedef struct _MMAPString MMAPString; + + + MMAPString is a string which size that can increase automatically. + _________________________________________________________________ + +constructor and destructor + +MMAPString * mmap_string_new(const char * init); + +MMAPString * mmap_string_new_len(const char * init, size_t len); + +MMAPString * mmap_string_sized_new(size_t dfl_size); + +void mmap_string_free(MMAPString * string); + + + mmap_string_new() allocates a new string. init is the intial value of + the string. NULL will be returned on error. + + mmap_string_new_len() allocates a new string. init is the intial value + of the string, len is the length of the initial string. NULL will be + returned on error. + + mmap_string_sized_new() allocates a new string. dfl_size is the + initial allocation of the string. NULL will be returned on error. + + mmap_string_free() release the memory used by the string. + _________________________________________________________________ + +string value modification + +MMAPString * mmap_string_assign(MMAPString * string, const char * rval); + +MMAPString * mmap_string_truncate(MMAPString *string, size_t len); + + + mmap_string_assign() sets a new value for the given string. NULL will + be returned on error. + + mmap_string_truncate() sets a length for the string. NULL will be + returned on error. +MMAPString * mmap_string_set_size (MMAPString * string, size_t len); + + + sets the allocation of the string. NULL will be returned on error. + _________________________________________________________________ + +insertion in string, deletion in string + +MMAPString * mmap_string_insert_len(MMAPString * string, size_t pos, + const char * val, size_t len); + +MMAPString * mmap_string_append(MMAPString * string, const char * val); + +MMAPString * mmap_string_append_len(MMAPString * string, + const char * val, size_t len); + +MMAPString * mmap_string_append_c(MMAPString * string, char c); + +MMAPString * mmap_string_prepend(MMAPString * string, const char * val); + +MMAPString * mmap_string_prepend_c(MMAPString * string, char c); + +MMAPString * mmap_string_prepend_len(MMAPString * string, const char * val, + size_t len); + +MMAPString * mmap_string_insert(MMAPString * string, size_t pos, + const char * val); + +MMAPString * mmap_string_insert_c(MMAPString *string, size_t pos, + char c); + +MMAPString * mmap_string_erase(MMAPString * string, size_t pos, + size_t len); + + + For complexity here, n is the size of the given MMAPString, and len is + the size of the string to insert. + + mmap_string_insert_len() inserts the given string value of given + length in the string at the given position. NULL will be returned on + error. Complexity is O(n + len). + + mmap_string_append() appends the given string value at the end of the + string. NULL will be returned on error. Complexity is O(len). + + mmap_string_append_len() appends the given string value of given + length at the end of the string. NULL will be returned on error. + Complexity is O(len). + + mmap_string_append_c() appends the given character at the end of the + string. NULL will be returned on error. Complexity is O(1). + + mmap_string_prepend() insert the given string value at the beginning + of the string. NULL will be returned on error. Complexity is O(n + + len). + + mmap_string_prepend_c() insert the given character at the beginning of + the string. NULL will be returned on error. Complexity is O(n). + + mmap_string_prepend_len() insert the given string value of given + length at the beginning of the string. NULL will be returned on error. + Complexity is O(n + len). + + mmap_string_insert() inserts the given string value in the string at + the given position. NULL will be returned on error. Complexity is O(n + + len). + + mmap_string_insert_c() inserts the given character in the string at + the given position. NULL will be returned on error. Complexity is + O(n). + + mmap_string_erase() removes the given count of characters (len) at the + given position of the string. NULL will be returned on error. + Complexity is O(n). + _________________________________________________________________ + +referencing string + +int mmap_string_ref(MMAPString * string); + +int mmap_string_unref(char * str); + + + MMAPString provides a mechanism that let you use MMAPString like + normal strings. You have first to use mmap_string_ref(), so that you + notify that the string will be used as a normal string, then, you use + mmapstr->str to refer to the string. When you have finished and you + want to free a string corresponding to a MMAPString, you will use + mmap_string_unref. + + mmap_string_ref() references the string so that the array of + characters can be used as a normal string then released with + mmap_string_unref(). The array of characters will be obtained with + string->str. returns -1 on error, 0 on success. + _________________________________________________________________ + +Chapter 3. Internet Message Format + + libEtPan! implements Internet Message parser. Currently, format is RFC + 2822. This module also allows to generate messages. + + Warning + + All allocation functions will take as argument allocated data and will + store these data in the structure they will allocate. Data should be + persistant during all the use of the structure and will be freed by + the free function of the structure + + allocation functions will return NULL on failure functions returning + integer will be returning one of the following error code: + MAILIMF_NO_ERROR, MAILIMF_ERROR_PARSE, MAILIMF_ERROR_MEMORY, + MAILIMF_ERROR_INVAL, or MAILIMF_ERROR_FILE. + _________________________________________________________________ + +Quick start + + You will need this module when you want to parse headers of messages + or when you want to build message headers conformant to standards. + _________________________________________________________________ + +Parse message headers + + You will use one of the four following functions, depending on your + needs : + + * mailimf_envelope_and_optional_fields_parse (the Section called + mailimf_envelope_and_optional_fields_parse), + * mailimf_envelope_fields_parse (the Section called + mailimf_envelope_fields_parse), + * mailimf_optional_fields_parse (the Section called + mailimf_optional_fields_parse), + * mailimf_fields_parse (the Section called mailimf_fields_parse). + _________________________________________________________________ + +Render the message headers + + Build your message headers, then use mailimf_fields_write (the Section + called Header fields) to render the headers. + _________________________________________________________________ + +Data types + +mailimf_mailbox - mailbox + + #include <libetpan/libetpan.h> struct mailimf_mailbox { char * + mb_display_name; /* can be NULL */ char * mb_addr_spec; /* != NULL */ + }; struct mailimf_mailbox * mailimf_mailbox_new(char * + mb_display_name, char * mb_addr_spec); void + mailimf_mailbox_free(struct mailimf_mailbox * mailbox); + + This is an email mailbox with a display name. + + Example 3-1. example of mailbox +DINH Viet Hoa <hoa@users.sourceforge.net> + + + mailimf_mailbox_new creates and initializes a data structure with a + value. Strings given as argument are referenced by the created object + and will be freed if the object is released. + + mailimf_mailbox_free frees memory used by the structure and + substructures will also be released. + + Example 3-2. mailbox creation and display +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_mailbox * mb; + char * display_name; + char * address; + + display_name = strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="); + address = strdup("dinh.viet.hoa@free.fr"); + mb = mailimf_mailbox_new(str, address); + /* do the things */ + mailimf_mailbox_free(mb); + + return 0; +} + +/* display mailbox information */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_mailbox(struct mailimf_mailbox * mb) +{ + if (mb->mb_display_name != NULL) + printf("display name: %s\n", mb->mb_display_name); + printf("address specifier : %s\n", mb->mb_addr_spec); +} + + _________________________________________________________________ + +mailimf_address - address + +#include <libetpan/libetpan.h> + +struct mailimf_address { + int ad_type; + union { + struct mailimf_mailbox * ad_mailbox; /* can be NULL */ + struct mailimf_group * ad_group; /* can be NULL */ + } ad_data; +}; + +struct mailimf_address * +mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox, + struct mailimf_group * ad_group); + +void mailimf_address_free(struct mailimf_address * address); + + + This is a mailbox or a group of mailbox. + + * ad_type can be MAILIMF_ADDRESS_MAILBOX or MAILIMF_ADDRESS_GROUP. + * ad_data.ad_mailbox is a mailbox if ad_type is + MAILIMF_ADDRESS_MAILBOX see the Section called mailimf_mailbox - + mailbox) + * ad_data.group is a group if type is MAILIMF_ADDRESS_GROUP. see the + Section called mailimf_group - named group of mailboxes) + + mailimf_address_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_address_free frees memory used by the structure and + substructures will also be released. + + Example 3-3. address creation and display +/* creates an address of type mailbox */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_address * a_mb; + struct mailimf_mailbox * mb; + char * display_name; + char * address; + + display_name = strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="); + address = strdup("dinh.viet.hoa@free.fr"); + mb = mailimf_mailbox_new(str, address); + + a_mb = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + /* do the things */ + mailimf_address_free(a_mb); +} + +/* creates an address of type group */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_address * a_g; + struct mailimf_group * g; + char * display_name; + + display_name = strdup("undisclosed-recipient"); + g = mailimf_group_new(display_name, NULL); + + a_g = mailimf_address_new(MAILIMF_ADDRESS_GROUP, NULL, g); + /* do the things */ + mailimf_address_free(a_g); + + return 0; +} + +/* display the content of an address */ + +#include <libetpan/libetpan.h> + +void display_address(struct mailimf_address * a) +{ + clistiter * cur; + + switch (a->ad_type) { + case MAILIMF_ADDRESS_GROUP: + display_mailimf_group(a->ad_data.ad_group); + break; + + case MAILIMF_ADDRESS_MAILBOX: + display_mailimf_mailbox(a->ad_data.ad_mailbox); + break; + } +} + + _________________________________________________________________ + +mailimf_mailbox_list - list of mailboxes + +#include <libetpan/libetpan.h> + +struct mailimf_mailbox_list { + clist * mb_list; /* list of (struct mailimf_mailbox *), != NULL */ +}; + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new(clist * mb_list); + +void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list); + + + This is a list of mailboxes. + + mb_list is a list of mailboxes. This is a clist which elements are of + type mailimf_mailbox (see the Section called mailimf_mailbox - + mailbox). + + mailimf_mailbox_list_new() creates and initializes a data structure + with a value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + + mailimf_mailbox_list_free() frees memory used by the structure and + substructures will also be released. + + Example 3-4. Creation and display of mailimf_mailbox_list +/* creates a list of mailboxes with two mailboxes */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_group * g; + char * display_name; + struct mailimf_mailbox_list * mb_list; + clist * list; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + list = clist_append(mb); + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + list = clist_append(mb); + + mb_list = mailimf_mailbox_list_new(list); + /* do the things */ + mailimf_mailbox_list_free(mb_list); + + return 0; +} + +/* display a list of mailboxes */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_mailbox_list(struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + display_mailbox(mb); + printf("\n"); + } +} + + _________________________________________________________________ + +mailimf_address_list - list of addresses + +#include <libetpan/libetpan.h> + +struct mailimf_address_list { + clist * ad_list; /* list of (struct mailimf_address *), != NULL */ +}; + +struct mailimf_address_list * +mailimf_address_list_new(clist * ad_list); + +void mailimf_address_list_free(struct mailimf_address_list * addr_list); + + + This is a list of addresses. + + ad_list is a list of addresses. This is a clist which elements are of + type mailimf_address (see the Section called mailimf_address - + address). + + mailimf_address_list_new() creates and initializes a data structure + with a value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + + mailimf_address_list_free() frees memory used by the structure and + substructures will also be released. + + Example 3-5. creation and display of list of addresses +/* creates a list of addresses with two addresses */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_address_list * addr_list; + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + list = clist_append(addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + list = clist_append(addr); + + addr_list = mailimf_address_list_new(list); + /* do the things */ + mailimf_address_list_free(mb_list); + + return 0; +} + +/* display a list of addresses */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_address_list(struct mailimf_address_list * addr_list) +{ + clistiter * cur; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + display_address(addr); + printf("\n"); + } +} + + _________________________________________________________________ + +mailimf_group - named group of mailboxes + +#include <libetpan/libetpan.h> + +struct mailimf_group { + char * grp_display_name; /* != NULL */ + struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */ +}; + +struct mailimf_group * +mailimf_group_new(char * grp_display_name, + struct mailimf_mailbox_list * grp_mb_list); + +void mailimf_group_free(struct mailimf_group * group); + + + This is a list of mailboxes tagged with a name. + + Example 3-6. example of group + they play music: <steve@morse.foo>, <neal@morse.foo>, + <yngwie@malmsteen.bar>, <michael@romeo.bar>; + + + grp_display_name is the name that will be displayed for this group, + for example 'group_name' in 'group_name: address1@domain1, + address2@domain2;'. This must be allocated with malloc(). grp_mb_list + is a list of mailboxes (see the Section called mailimf_mailbox_list - + list of mailboxes). + + mailimf_group_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_group_free() frees memory used by the structure and + substructures will also be released. + + Example 3-7. creation and display of a group +/* creates an empty group */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_group * g; + char * display_name; + + display_name = strdup("undisclosed-recipient"); + g = mailimf_group_new(display_name, NULL); + /* do the things */ + mailimf_group_free(g); +} + +/* creates a group with two mailboxes */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_group * g; + char * display_name; + struct mailimf_mailbox_list * mb_list; + struct mailimf_mailbox * mb; + clist * list; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + list = clist_append(mb); + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + list = clist_append(mb); + + mb_list = mailimf_mailbox_list_new(list); + + display_name = strdup("my_group"); + g = mailimf_group_new(display_name, mb_list); + /* do the things */ + mailimf_group_free(g); + + return 0; +} + +/* display content of group */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_group(struct mailimf_group * group) +{ + printf("name of the group: %s\n", a->group->display_name); + for(cur = clist_begin(a->group->mb_list->list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + display_mailbox(mb); + printf("\n"); + } +} + + _________________________________________________________________ + +mailimf_date_time - date of a message + + #include <libetpan/libetpan.h> struct mailimf_date_time { int dt_day; + int dt_month; int dt_year; int dt_hour; int dt_min; int dt_sec; int + dt_zone; }; struct mailimf_date_time * mailimf_date_time_new(int + dt_day, int dt_month, int dt_year, int dt_hour, int dt_min, int + dt_sec, int dt_zone); void mailimf_date_time_free(struct + mailimf_date_time * date_time); + + This is the date and time of a message. For example : + + Example 3-8. example of date +Thu, 11 Dec 2003 00:15:02 +0100. + + + * dt_day is the day of month (1 to 31) + * dt_month (1 to 12) + * dt_year (4 digits) + * dt_hour (0 to 23) + * dt_min (0 to 59) + * dt_sec (0 to 59) + * dt_zone (this is the decimal value that we can read, for example: + for '-0200', the value is -200). + + mailimf_date_time_new() creates and initializes a date structure with + a value. + + mailimf_date_time_free() frees memory used by the structure. + + Example 3-9. creation and display of date +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_date_time * d; + + d = mailimf_date_time_new(9, 5, 2003, 3, 01, 40, -0200); + /* do the things */ + mailimf_date_time_free(d); + + return 0; +} + +/* display the date */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_date(struct mailimf_date_time * d) +{ + printf("%02i/%02i/%i %02i:%02i:%02i %+04i\n", + d->dt_day, d->dt_month, d->dt_year, + d->dt_hour, d->dt_min, d->dt_sec, d->dt_zone); +} + + _________________________________________________________________ + +mailimf_orig_date - parsed content of date header + +#include <libetpan/libetpan.h> + +struct mailimf_orig_date { + struct mailimf_date_time * dt_date_time; /* != NULL */ +}; + +struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time * + dt_date_time); + +void mailimf_orig_date_free(struct mailimf_orig_date * orig_date); + + + This is the content of a header Date or Resent-Date. It encapsulates a + mailimf_date_time + + dt_date_time is the parsed date (see the Section called + mailimf_date_time - date of a message). + + mailimf_orig_date_new() creates and initializes a data structure with + a value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_orig_date_free() frees memory used by the structure and + substructures will also be released. + + Example 3-10. creation and display of Date field +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_date_time * d; + struct mailimf_orig_date * date; + + d = mailimf_date_time_new(9, 5, 2003, 3, 01, 40, -0200); + date = mailimf_orig_date_new(d); + /* do the things */ + mailimf_orig_date_free(date); + + return 0; +} + +/* display date header */ + +#include <libetpan/libetpan.h> + +void display_orig_date(struct mailimf_orig_date * orig_date) +{ + display_date_time(d->dt_date_time); +} + + _________________________________________________________________ + +mailimf_from - parsed content of From header + +#include <libetpan/libetpan.h> + +struct mailimf_from { + struct mailimf_mailbox_list * frm_mb_list; /* != NULL */ +}; + +struct mailimf_from * +mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list); + +void mailimf_from_free(struct mailimf_from * from); + + + This is the content of a header From or Resent-From. + + frm_mb_list is the parsed mailbox list (see the Section called + mailimf_mailbox_list - list of mailboxes). + + mailimf_from_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_from_free() frees memory used by the structure and + substructures will also be released. + + Example 3-11. creation and display of a From header +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + /* do the things */ + mailimf_from_free(from); + + return 0; +} + +/* display content of from header */ + +#include <libetpan/libetpan.h> + +void display_from(struct mailimf_from * from) +{ + display_mailbox_list(from->frm_mb_list); +} + + _________________________________________________________________ + +mailimf_sender - parsed content of Sender header + +#include <libetpan/libetpan.h> + +struct mailimf_sender { + struct mailimf_mailbox * snd_mb; /* != NULL */ +}; + +struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb); + +void mailimf_sender_free(struct mailimf_sender * sender); + + + This is the content of a header Sender or Resent-Sender. + + snd_mb is the parsed mailbox (see the Section called mailimf_mailbox - + mailbox). + + mailimf_sender_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_sender_free() This function frees memory used by the structure + and substructures will also be released. + + Example 3-12. creation and display of Sender field +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + + sender = mailimf_sender_new(mb); + /* do the things */ + mailimf_sender_free(sender); + + return 0; +} + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_sender(struct mailimf_sender * sender) +{ + display_mailbox(sender->snd_mb); +} + + _________________________________________________________________ + +mailimf_reply_to - parsed content of Reply-To header + +#include <libetpan/libetpan.h> + +struct mailimf_reply_to { + struct mailimf_address_list * rt_addr_list; /* != NULL */ +}; + +struct mailimf_reply_to * +mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list); + +void mailimf_reply_to_free(struct mailimf_reply_to * reply_to); + + + This is the content of a header Reply-To. + + addr_list is the parsed address list (see the Section called + mailimf_address_list - list of addresses). + + mailimf_reply_to_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_reply_to_free() frees memory used by the structure and + substructures will also be released. + + Example 3-13. creation and display of Reply-To field +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_reply_to * reply_to; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + reply_to = mailimf_reply_to_new(addr_list); + /* do the things */ + mailimf_reply_to_free(reply_to); + + return 0; +} + +/* display Reply-To header */ + +#include <libetpan/libetpan.h> + +void display_reply_to(struct mailimf_reply_to * reply_to) +{ + display_address_list(reply_to->addr_list); +} + + _________________________________________________________________ + +mailimf_to - parsed content of To header + + struct mailimf_to { + struct mailimf_address_list * to_addr_list; /* != NULL */ +}; + +struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list); + +void mailimf_to_free(struct mailimf_to * to); + + + This is the content of a header To or Resent-To. + + to_addr_list is the parsed address list (see the Section called + mailimf_address_list - list of addresses). + + mailimf_to_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_to_free() frees memory used by the structure and substructures + will also be released. + + Example 3-14. creation and display of To field +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + /* do the things */ + mailimf_to_free(to); + + return 0; +} + +/* display To header */ + +#include <libetpan/libetpan.h> + +void display_to(struct mailimf_to * to) +{ + display_address_list(to->to_addr_list); +} + + _________________________________________________________________ + +mailimf_cc - parsed content of Cc + +#include <libetpan/libetpan.h> + +struct mailimf_cc { + struct mailimf_address_list * cc_addr_list; /* != NULL */ +}; + +struct mailimf_cc * +mailimf_cc_new(struct mailimf_address_list * cc_addr_list); + +void mailimf_cc_free(struct mailimf_cc * cc); + + This is the content of a header Cc or Resent-Cc. + + cc_addr_list is the parsed address list (see the Section called + mailimf_address_list - list of addresses). + + mailimf_cc_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_cc_free() This function frees memory used by the structure and + substructures will also be released. + + Example 3-15. creation and display of Cc field +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + cc = mailimf_cc_new(addr_list); + /* do the things */ + mailimf_cc_free(cc); + + return 0; +} + +/* display content of Cc field */ + +#include <libetpan/libetpan.h> + +void display_cc(struct mailimf_cc * cc) +{ + display_address_list(cc->cc_addr_list); +} + + + _________________________________________________________________ + +mailimf_bcc - parsed content of Bcc field + +#include <libetpan/libetpan.h> + +struct mailimf_bcc { + struct mailimf_address_list * bcc_addr_list; /* can be NULL */ +}; + +struct mailimf_bcc * +mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list); + +void mailimf_bcc_free(struct mailimf_bcc * bcc); + + + This is the content of a header Bcc or Resent-Bcc. + + bcc_addr_list is the parsed address list (see the Section called + mailimf_address_list - list of addresses). + + mailimf_bcc_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_bcc_free() frees memory used by the structure and + substructures will also be released. + + Example 3-16. creation and display of Bcc field +/* create visible Bcc */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + bcc = mailimf_bcc_new(addr_list); + /* do the things */ + mailimf_bcc_free(bcc); + + return 0; +} + +/* create unvisible Bcc */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_bcc * bcc; + + bcc = mailimf_bcc_new(NULL); + /* do the things */ + mailimf_bcc_free(bcc); + + return 0; +} + +/* display content of Bcc field */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_bcc(struct mailimf_bcc * bcc) +{ + if (bcc->addr_list == NULL) { + printf("hidden Bcc\n"); + } + else { + display_address_list(bcc->bcc_addr_list); + } +} + + _________________________________________________________________ + +mailimf_message_id - parsed content of Message-ID header + +#include <libetpan/libetpan.h> + +struct mailimf_message_id { + char * mid_value; /* != NULL */ +}; + +struct mailimf_message_id * mailimf_message_id_new(char * mid_value); + +void mailimf_message_id_free(struct mailimf_message_id * message_id); + + + This is the content of a header Message-ID or Resent-Message-ID. For + example : + + Example 3-17. example of Message-ID +Message-ID: <200312100009.43592@c01n-c01n.plop.P4N>> + + + mid_value is the message identifier. It is not enclosed by angle + bracket. + + mailimf_message_id_new() This function creates and initializes a data + structure with a value. Structures given as argument are referenced by + the created object and will be freed if the object is released. + + The given string is allocated with malloc() and is not enclosed by + angle bracket. + + mailimf_message_id_free() frees memory used by the structure and + substructures will also be released. + + Example 3-18. creation and display of Message-ID field +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_message_id * msg_id; + char * id; + + id = strdup("1037197913.3dd26259752fa@imp.free.fr"); + msg_id = mailimf_message_id_new(id); + /* do the things */ + mailimf_message_id_free(msg_id); + + return 0; +} + +/* display message id */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_message_id(struct mailimf_message_id * msg_id) +{ + printf("%s\n", msg_id->mid_value); +} + + _________________________________________________________________ + +mailimf_in_reply_to - parsed content of In-Reply-To field + +#include <libetpan/libetpan.h> + +struct mailimf_in_reply_to { + clist * mid_list; /* list of (char *), != NULL */ +}; + +struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list); + +void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to); + + + content of a header In-Reply-To. For example : +In-Reply-To: <etPan.3fd5fa29.4c3901c1.6b39@homer> + + + mid_list is a clist in which elements are message identifiers. their + types are (char *) and they are allocated with malloc(). + + mailimf_in_reply_to_new() creates and initializes a data structure + with a value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + + mailimf_in_reply_to_free() frees memory used by the structure and + substructures will also be released. + + Example 3-19. creation and display of In-Reply-To field +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_in_reply_to * in_reply_to; + clist * msg_id_list; + + msg_id_list = clist_new(); + clist_append(msg_id_list, + strdup("etPan.3ebbcc18.4014197f.bc1@homer.invalid")); + + in_reply_to = mailimf_in_reply_to_new(msg_id_list); + /* do the things */ + mailimf_in_reply_to_free(in_reply_to); + + return 0; +} + +/* display the content of mailimf_in_reply_to */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_in_reply_to(struct mailimf_in_reply_to * in_reply_to) +{ + clistiter * cur; + + for(cur = clist_begin(in_reply_to->mid_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * str; + + str = clist_content(cur); + + printf("%s\n", str); + } +} + + _________________________________________________________________ + +mailimf_references - parsed content of References field + +#include <libetpan/libetpan.h> + +struct mailimf_references { + clist * mid_list; /* list of (char *) */ + /* != NULL */ +}; + +struct mailimf_references * mailimf_references_new(clist * mid_list); + +void mailimf_references_free(struct mailimf_references * references); + + + This is the content of a header References. For example : +In-Reply-To: <etPan.3fd5fa29.4c3901c1.6b39@homer> + <3FD5FA78.A1D98E7@oleane.net> + <etPan.3fd5fc69.2b349482.730e@homer> + + + mid_list is a clist in which elements are message identifiers. their + types are (char *) and they are allocated with malloc(). + + mailimf_references_new() creates and initializes a data structure with + a value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_references_free() frees memory used by the structure and + substructures will also be released. + + Example 3-20. creation and display of References field +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_references * ref; + clist * msg_id_list; + + msg_id_list = clist_new(); + clist_append(msg_id_list, + strdup("200304280144.23633.wim.delvaux@adaptiveplanet.com")); + clist_append(msg_id_list, + strdup("200304301153.19688.wim.delvaux@adaptiveplanet.com")); + clist_append(msg_id_list, + strdup("etPan.3eb29de4.5fc4d652.3f83@homer")); + + ref = mailimf_references_new(msg_id_list); + /* do the things */ + mailimf_in_reply_to_free(ref); + + return 0; +} + +/* display references */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_references(struct mailimf_references * ref) +{ + clistiter * cur; + + for(cur = clist_begin(ref->mid_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * msg_id; + + msg_id = clist_content(cur); + + printf("%s\n", msg_id); + } +} + + _________________________________________________________________ + +mailimf_subject - parsed content of Subject field + +#include <libetpan/libetpan.h> + +struct mailimf_subject { + char * sbj_value; /* != NULL */ +}; + +struct mailimf_subject * mailimf_subject_new(char * sbj_value); + +void mailimf_subject_free(struct mailimf_subject * subject); + + This is the content of a header Subject. + + sbj_value is the value of the field. + + mailimf_subject_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_subject_free frees memory used by the structure and + substructures will also be released. + + Example 3-21. creation and display of Subject field +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_subject * subject; + + subject = mailimf_subject_new(strdup("example of subject")); + /* do the things */ + mailimf_subject_free(subject); + + return 0; +} + +/* display subject header */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_subject(struct mailimf_subject * subject) +{ + printf("%s\n", subject->value); +} + + _________________________________________________________________ + +mailimf_comments - parsed content of Comments field + +#include <libetpan/libetpan.h> + +struct mailimf_comments { + char * cm_value; /* != NULL */ +}; + +struct mailimf_comments * mailimf_comments_new(char * cm_value); + +void mailimf_comments_free(struct mailimf_comments * comments); + + + This is the content of a header Comments. + + cm_value is the value of the field. + + mailimf_comments_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_comments_free() frees memory used by the structure and + substructures will also be released. + + Example 3-22. creation and display of Comment field +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_comments * comments; + + comments = mailimf_comments_new(strdup("example of comment")); + /* do the things */ + mailimf_comments_free(comments); + + return 0; +} + +/* display the content of a comments */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_comments(struct mailimf_comments * comments) +{ + printf("%s\n", comments->cm_value); +} + + _________________________________________________________________ + +mailimf_keywords - parsed content of Keywords field + +#include <libetpan/libetpan.h> + +struct mailimf_keywords { + clist * kw_list; /* list of (char *), != NULL */ +}; + +struct mailimf_keywords * mailimf_keywords_new(clist * kw_list); + +void mailimf_keywords_free(struct mailimf_keywords * keywords); + + + This is the content of a header Keywords. + + kw_list is the list of keywords. This is a list of (char *) allocated + with malloc(). + + mailimf_keywords_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_keywords_free() frees memory used by the structure and + substructures will also be released. + + Example 3-23. creation and display of Keywords field +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_keywords * keywords; + clist * list; + + list = clist_new(); + clist_append(list, strdup("sauerkraut")); + clist_append(list, strdup("potatoes")); + clist_append(list, strdup("cooking")); + + keywords = mailimf_keywords_new(list); + /* do the things */ + mailimf_keywords_free(keywords); + + return 0; +} + +/* display the content of mailimf_in_reply_to */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_keywords(struct mailimf_keywords * kw) +{ + clistiter * cur; + + for(cur = clist_begin(kw->kw_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * str; + + str = clist_content(cur); + + printf("%s\n", str); + } +} + + _________________________________________________________________ + +mailimf_return - parsed content of Return-Path field + +#include <libetpan/libetpan.h> + +struct mailimf_return { + struct mailimf_path * ret_path; /* != NULL */ +}; + +struct mailimf_return * +mailimf_return_new(struct mailimf_path * ret_path); + +void mailimf_return_free(struct mailimf_return * return_path); + + + This is the content of a header Return-Path. + + ret_path is the parsed value of Return-Path (see the Section called + mailimf_path - address in Return-Path field). + + mailimf_return_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_return_free() frees memory used by the structure and + substructures will also be released. + + Example 3-24. creation and display of Return-Path field +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_path * path; + struct mailimf_return * r; + + path = mailimf_path_new(strdup("dinh.viet.hoa@free.fr")); + r = mailimf_return_new(path); + /* do the things */ + mailimf_return_free(r); + + return 0; +} + +/* display return path */ + +#include <libetpan/libetpan.h> + +void display_return(struct mailimf_return * r) +{ + display_path(r->ret_path); +} + + _________________________________________________________________ + +mailimf_path - address in Return-Path field + +#include <libetpan/libetpan.h> + +struct mailimf_path { + char * pt_addr_spec; /* can be NULL */ +}; + +struct mailimf_path * mailimf_path_new(char * pt_addr_spec); + +void mailimf_path_free(struct mailimf_path * path); + + + This is the encapsulation of address specifier for Return-Path + content. + + pt_addr_spec is a mailbox destination. + + mailimf_path_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + The given string is allocated with malloc(). This is a address + specifier. + + mailimf_path_free() frees memory used by the structure and + substructures will also be released. + + Example 3-25. Creation and display of return path + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_path * path; + + path = mailimf_path_new(strdup("dinh.viet.hoa@free.fr")); + /* do the things */ + mailimf_path_free(r); + + return 0; +} + +/* display return path */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_path(struct mailimf_path * path) +{ + printf("%s\n", path->pt_addr_spec); +} + + _________________________________________________________________ + +mailimf_optional_field - non-standard header + +#include <libetpan/libetpan.h> + +struct mailimf_optional_field { + char * fld_name; /* != NULL */ + char * fld_value; /* != NULL */ +}; + +struct mailimf_optional_field * +mailimf_optional_field_new(char * fld_name, char * fld_value); + +void mailimf_optional_field_free(struct mailimf_optional_field * opt_field); + + + This is a non-standard header or unparsed header. + + * fld_name is the name of the header field. + * fld_value is the value of the header field. + + mailimf_optional_field_new() This function creates and initializes a + data structure with a value. Structures given as argument are + referenced by the created object and will be freed if the object is + released. + + field name and field value have to be allocated with malloc(). + + mailimf_optional_field_free() This function frees memory used by the + structure and substructures will also be released. + + Example 3-26. creation and display of non-standard fields +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_optional_field * opt; + + opt = mailimf_optional_field_new(strdup("X-My-Field"), strdup("my value")); + /* do the things */ + mailimf_optional_field_free(opt); + + return 0; +} + +/* display the optional field */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_optional_field(struct mailimf_optional_field * opt) +{ + printf("%s: %s\n", opt->fld_name, opt->fld_value); +} + + _________________________________________________________________ + +mailimf_field - header field + +#include <libetpan/libetpan.h> + +enum { + MAILIMF_FIELD_NONE, /* on parse error */ + MAILIMF_FIELD_RETURN_PATH, /* Return-Path */ + MAILIMF_FIELD_RESENT_DATE, /* Resent-Date */ + MAILIMF_FIELD_RESENT_FROM, /* Resent-From */ + MAILIMF_FIELD_RESENT_SENDER, /* Resent-Sender */ + MAILIMF_FIELD_RESENT_TO, /* Resent-To */ + MAILIMF_FIELD_RESENT_CC, /* Resent-Cc */ + MAILIMF_FIELD_RESENT_BCC, /* Resent-Bcc */ + MAILIMF_FIELD_RESENT_MSG_ID, /* Resent-Message-ID */ + MAILIMF_FIELD_ORIG_DATE, /* Date */ + MAILIMF_FIELD_FROM, /* From */ + MAILIMF_FIELD_SENDER, /* Sender */ + MAILIMF_FIELD_REPLY_TO, /* Reply-To */ + MAILIMF_FIELD_TO, /* To */ + MAILIMF_FIELD_CC, /* Cc */ + MAILIMF_FIELD_BCC, /* Bcc */ + MAILIMF_FIELD_MESSAGE_ID, /* Message-ID */ + MAILIMF_FIELD_IN_REPLY_TO, /* In-Reply-To */ + MAILIMF_FIELD_REFERENCES, /* References */ + MAILIMF_FIELD_SUBJECT, /* Subject */ + MAILIMF_FIELD_COMMENTS, /* Comments */ + MAILIMF_FIELD_KEYWORDS, /* Keywords */ + MAILIMF_FIELD_OPTIONAL_FIELD, /* other field */ +}; + +struct mailimf_field { + int fld_type; + union { + struct mailimf_return * fld_return_path; /* can be NULL */ + struct mailimf_orig_date * fld_resent_date; /* can be NULL */ + struct mailimf_from * fld_resent_from; /* can be NULL */ + struct mailimf_sender * fld_resent_sender; /* can be NULL */ + struct mailimf_to * fld_resent_to; /* can be NULL */ + struct mailimf_cc * fld_resent_cc; /* can be NULL */ + struct mailimf_bcc * fld_resent_bcc; /* can be NULL */ + struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */ + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ + struct mailimf_optional_field * fld_optional_field; /* can be NULL */ + } fld_data; +}; + +struct mailimf_field * +mailimf_field_new(int fld_type, + struct mailimf_return * fld_return_path, + struct mailimf_orig_date * fld_resent_date, + struct mailimf_from * fld_resent_from, + struct mailimf_sender * fld_resent_sender, + struct mailimf_to * fld_resent_to, + struct mailimf_cc * fld_resent_cc, + struct mailimf_bcc * fld_resent_bcc, + struct mailimf_message_id * fld_resent_msg_id, + struct mailimf_orig_date * fld_orig_date, + struct mailimf_from * fld_from, + struct mailimf_sender * fld_sender, + struct mailimf_reply_to * fld_reply_to, + struct mailimf_to * fld_to, + struct mailimf_cc * fld_cc, + struct mailimf_bcc * fld_bcc, + struct mailimf_message_id * fld_message_id, + struct mailimf_in_reply_to * fld_in_reply_to, + struct mailimf_references * fld_references, + struct mailimf_subject * fld_subject, + struct mailimf_comments * fld_comments, + struct mailimf_keywords * fld_keywords, + struct mailimf_optional_field * fld_optional_field); + +void mailimf_field_free(struct mailimf_field * field); + + + This is one header field of a message. + + * type is the type of the field. This define the type of the field. + Only the corresponding field should be, then, filled. The value of + this field can be one of : MAILIMF_FIELD_RETURN_PATH, + MAILIMF_FIELD_RESENT_DATE, MAILIMF_FIELD_RESENT_FROM, + MAILIMF_FIELD_RESENT_SENDER, MAILIMF_FIELD_RESENT_TO, + MAILIMF_FIELD_RESENT_CC, MAILIMF_FIELD_RESENT_BCC, + MAILIMF_FIELD_RESENT_MSG_ID, MAILIMF_FIELD_ORIG_DATE, + MAILIMF_FIELD_FROM, MAILIMF_FIELD_SENDER, MAILIMF_FIELD_REPLY_TO, + MAILIMF_FIELD_TO, MAILIMF_FIELD_CC, MAILIMF_FIELD_BCC, + MAILIMF_FIELD_MESSAGE_ID, MAILIMF_FIELD_IN_REPLY_TO, + MAILIMF_FIELD_REFERENCES, MAILIMF_FIELD_SUBJECT, + MAILIMF_FIELD_COMMENTS, MAILIMF_FIELD_KEYWORDS, + MAILIMF_FIELD_OPTIONAL_FIELD. + * fld_data.fld_return_path is the parsed content of the Return-Path + field if type is MAILIMF_FIELD_RETURN_PATH (see the Section called + mailimf_return - parsed content of Return-Path field). + * fld_data.fld_resent_date is the parsed content of the Resent-Date + field if type is MAILIMF_FIELD_RESENT_DATE (see the Section called + mailimf_orig_date - parsed content of date header). + * fld_data.fld_resent_from is the parsed content of the Resent-From + field if type is MAILIMF_FIELD_RESENT_FROM (see the Section called + mailimf_from - parsed content of From header). + * fld_data.fld_resent_sender is the parsed content of the + Resent-Sender field if type is MAILIMF_FIELD_RESENT_SENDER (see + the Section called mailimf_sender - parsed content of Sender + header). + * fld_data.fld_resent_to is the parsed content of the Resent-To + field if type is MAILIMF_FIELD_RESENT_TO (see the Section called + mailimf_to - parsed content of To header). + * fld_data.fld_resent_cc is the parsed content of the Resent-Cc + field if type is MAILIMF_FIELD_CC (see the Section called + mailimf_cc - parsed content of Cc). + * fld_data.fld_resent_bcc is the parsed content of the Resent-Bcc + field if type is MAILIMF_FIELD_BCC (see the Section called + mailimf_bcc - parsed content of Bcc field). + * fld_data.fld_resent_msg_id is the parsed content of the + Resent-Message-ID field if type is MAILIMF_FIELD_RESENT_MSG_ID + (see the Section called mailimf_message_id - parsed content of + Message-ID header). + * fld_data.fld_orig_date is the parsed content of the Date field if + type is MAILIMF_FIELD_ORIG_DATE (see the Section called + mailimf_orig_date - parsed content of date header). + * fld_data.fld_from is the parsed content of the From field if type + is MAILIMF_FIELD_FROM (see the Section called mailimf_from - + parsed content of From header). + * fld_data.fld_sender is the parsed content of the Sender field if + type is MAILIMF_FIELD_SENDER (see the Section called + mailimf_sender - parsed content of Sender header). + * fld_data.fld_reply_to is the parsed content of the Reply-To field + if type is MAILIMF_FIELD_REPLY_TO (see the Section called + mailimf_reply_to - parsed content of Reply-To header). + * fld_data.fld_to is the parsed content of the To field if type is + MAILIMF_FIELD_TO (see the Section called mailimf_to - parsed + content of To header). + * fld_data.fld_cc is the parsed content of the Cc field if type is + MAILIMF_FIELD_CC (see the Section called mailimf_cc - parsed + content of Cc). + * fld_data.fld_bcc is the parsed content of the Bcc field if type is + MAILIMF_FIELD_BCC (see the Section called mailimf_bcc - parsed + content of Bcc field). + * fld_data.fld_message_id is the parsed content of the Message-ID + field if type is MAILIMF_FIELD_MESSAGE_ID (see the Section called + mailimf_message_id - parsed content of Message-ID header). + * fld_data.fld_in_reply_to is the parsed content of the In-Reply-To + field if type is MAILIMF_FIELD_IN_REPLY_TO (see the Section called + mailimf_in_reply_to - parsed content of In-Reply-To field). + * fld_data.fld_references is the parsed content of the References + field if type is MAILIMF_FIELD_REFERENCES (see the Section called + mailimf_references - parsed content of References field). + * fld_data.fld_subject is the content of the Subject field if type + is MAILIMF_FIELD_SUBJECT (see the Section called mailimf_subject - + parsed content of Subject field). + * fld_data.fld_comments is the content of the Comments field if type + is MAILIMF_FIELD_COMMENTS (see the Section called mailimf_comments + - parsed content of Comments field). + * fld_data.fld_keywords is the parsed content of the Keywords field + if type is MAILIMF_FIELD_KEYWORDS (see the Section called + mailimf_keywords - parsed content of Keywords field). + * fld_data.fld_optional_field is an other field and is not parsed if + type is MAILIMF_FIELD_OPTIONAL_FIELD (see the Section called + mailimf_optional_field - non-standard header). + + mailimf_field_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_field_free() frees memory used by the structure and + substructures will also be released. + + Example 3-27. creation and display of field +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_field * f; + struct mailimf_mailbox * mb; + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + /* do the things */ + mailimf_field_free(f); + + return 0; +} + +/* display content of the header */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_field(struct mailimf_field * field) +{ + switch (field->type) { + case MAILIMF_FIELD_RETURN_PATH: + printf("Return-Path:\n"); + display_return(field->fld_data.fld_return_path); + break; + case MAILIMF_FIELD_RESENT_DATE: + printf("Resent-Date:\n"); + display_orig_date(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_RESENT_FROM: + printf("Resent-From:\n"); + display_from(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_RESENT_SENDER: + printf("Resent-Sender:\n"); + display_sender(field->fld_data.fld_resent_sender); + break; + case MAILIMF_FIELD_RESENT_TO: + printf("Resent-To:\n"); + display_to(field->fld_data.fld_resent_to); + break; + case MAILIMF_FIELD_RESENT_CC: + printf("Resent-Cc:\n"); + display_from(field->fld_data.fld_resent_cc); + break; + case MAILIMF_FIELD_RESENT_BCC: + printf("Resent-Bcc:\n"); + display_from(field->fld_data.fld_resent_bcc); + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + printf("Resent-Message-ID:\n"); + display_message_id(field->fld_data.fld_resent_msg_id); + break; + case MAILIMF_FIELD_ORIG_DATE: + printf("Date:\n"); + display_orig_date(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + printf("From:\n"); + display_from(field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + printf("Sender:\n"); + display_sender(field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + printf("Reply-To:\n"); + display_reply_to(field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + printf("To:\n"); + display_to(field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + printf("Cc:\n"); + display_cc(field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + printf("Bcc:\n"); + display_bcc(field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + printf("Message-ID:\n"); + display_message_id(field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + printf("In-Reply-To:\n"); + display_in_reply_to(field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + printf("References:\n"); + display_references(field->fld_data.fld_references_to); + break; + case MAILIMF_FIELD_SUBJECT: + printf("Subject:\n"); + display_subject(field->fld_data.fld_subject); + break; + case MAILIMF_FIELD_COMMENTS: + printf("Comments:\n"); + display_comments(field->fld_data.fld_comments); + break; + case MAILIMF_FIELD_KEYWORDS: + printf("Keywords:\n"); + display_keywords(field->fld_data.fld_keywords); + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + printf("[optional field]:\n"); + display_optional_field(field->fld_data.fld_optional_field); + break; + } +} + + _________________________________________________________________ + +mailimf_fields - list of header fields + +#include <libetpan/libetpan.h> + +struct mailimf_fields { + clist * fld_list; /* list of (struct mailimf_field *), != NULL */ +}; + +struct mailimf_fields * mailimf_fields_new(clist * fld_list); + +void mailimf_fields_free(struct mailimf_fields * fields); + + + This is the list of header fields of a message. + + fld_list is a list of header fields. This is a clist which elements + are of type mailimf_field (see the Section called mailimf_field - + header field). + + mailimf_fields_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_fields_free() frees memory used by the structure and + substructures will also be released. + + Example 3-28. creation and display of header fields +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_field * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + /* do the things */ + mailimf_fields_free(fields); + + return 0; +} + +/* display list of headers */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_fields(struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(field->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_field * f; + + f = clist_content(cur); + + display_field(f); + printf("\n"); + } +} + + _________________________________________________________________ + +mailimf_body - message body without headers + +#include <libetpan/libetpan.h> + +struct mailimf_body { + const char * bd_text; /* != NULL */ + size_t bd_size; +}; + +struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size); + +void mailimf_body_free(struct mailimf_body * body); + + + This is the text content of a message (without headers). + + * bd_text is the beginning of the text part, it is a substring of an + other string. It is not necessarily zero terminated. + * bd_size is the size of the text part + + mailimf_body_new() creates and initializes a data structure with a + value. Text given as argument will NOT be released. + + mailimf_body_free() frees memory used by the structure. + + Example 3-29. creation and display of message body +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_body * b; + + b = mailimf_body_new("this is the content of the message", 34); + /* do the things */ + mailimf_body_free(b); + + return 0; +} + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_body(struct mailimf_body * b) +{ + char * text; + + text = malloc(b->size + 1); + strncpy(text, b->bd_text, b->bd_size); + text[b->size] = 0; + + puts(text); + printf("\n"); + + free(text); + + return 0; +} + + _________________________________________________________________ + +mailimf_message - parsed message + +#include <libetpan/libetpan.h> + +struct mailimf_message { + struct mailimf_fields * msg_fields; /* != NULL */ + struct mailimf_body * msg_body; /* != NULL */ +}; + +struct mailimf_message * +mailimf_message_new(struct mailimf_fields * msg_fields, + struct mailimf_body * msg_body); + +void mailimf_message_free(struct mailimf_message * message); + + + This is the message content (text and headers). + + * msg_fields is the header fields of the message (see the Section + called mailimf_fields - list of header fields). + * msg_body is the text part of the message (see the Section called + mailimf_body - message body without headers). + + mailimf_message_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailimf_message_free() frees memory used by the structure and + substructures will also be released. + + Example 3-30. creation and display of message +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_body * b; + struct mailimf_message * m; + struct mailimf_fields * fields; + struct mailimf_fields * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build text content */ + + b = mailimf_body_new("this is the content of the message", 34); + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + + /* build message */ + + m = mailimf_message_new(fields, b); + /* do the things */ + mailimf_message_free(m); + + return 0; +} + +/* display the message */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_message(struct mailimf_message * msg) +{ + display_fields(msg->msg_fields); + printf("\n"); + display_body(msg->msg_body); + printf("\n"); +} + + _________________________________________________________________ + +mailimf_single_fields - simplified fields + +#include <libetpan/libetpan.h> + +struct mailimf_single_fields { + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ +}; + +struct mailimf_single_fields * +mailimf_single_fields_new(struct mailimf_fields * fields); + +void mailimf_single_fields_free(struct mailimf_single_fields * + single_fields); + +void mailimf_single_fields_init(struct mailimf_single_fields * single_fields, + struct mailimf_fields * fields); + + Structure that contains some standard fields and allows access to a + given header without running through the list. + + mailimf_fields is the native structure that IMF module will use, this + module will provide an easier structure to use when parsing fields. + mailimf_single_fields is an easier structure to get parsed fields, + rather than iteration over the list of fields + + * fld_orig_date is the parsed "Date" field (see the Section called + mailimf_orig_date - parsed content of date header). + * fld_from is the parsed "From" field (see the Section called + mailimf_from - parsed content of From header). + * fld_sender is the parsed "Sender "field (see the Section called + mailimf_sender - parsed content of Sender header). + * reply_to is the parsed "Reply-To" field (see the Section called + mailimf_reply_to - parsed content of Reply-To header). + * fld_to is the parsed "To" field (see the Section called mailimf_to + - parsed content of To header). + * fld_cc is the parsed "Cc" field (see the Section called mailimf_cc + - parsed content of Cc). + * fld_bcc is the parsed "Bcc" field (see the Section called + mailimf_bcc - parsed content of Bcc field). + * fld_message_id is the parsed "Message-ID" field. (see the Section + called mailimf_message_id - parsed content of Message-ID header). + * fld_in_reply_to is the parsed "In-Reply-To" field. (see the + Section called mailimf_in_reply_to - parsed content of In-Reply-To + field). + * fld_references is the parsed "References" field. (see the Section + called mailimf_references - parsed content of References field). + * fld_subject is the parsed "Subject" field (see the Section called + mailimf_subject - parsed content of Subject field). + * fld_comments is the parsed "Comments" field (see the Section + called mailimf_comments - parsed content of Comments field). + * fld_keywords is the parsed "Keywords" field (see the Section + called mailimf_keywords - parsed content of Keywords field). + + mailimf_single_fields_new() creates and initializes a data structure + with a value. Structures given as argument are referenced by the + created object and will NOT be freed if the object is released. + + mailimf_single_fields_free() frees memory used by the structure and + substructures will NOT be released. They should be released by the + application. + + mailimf_single_fields_init() will initialize fill the data structure, + using the given argument (fields). The interesting fields will be + filled into single_fields. + + Example 3-31. using mailimf_single_fields +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_single_fields * single_fields; + struct mailimf_fields * fields; + struct mailimf_field * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + + /* create the single fields */ + single_fields = mailimf_single_fields_new(fields); + /* do the things */ + mailimf_single_fields_free(single_fields); + mailimf_fields_free(fields); + + return 0; +} + + + Example 3-32. using mailimf_single_fields without memory allocation +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_single_fields single_fields; + struct mailimf_fields * fields; + struct mailimf_field * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + + /* fill the single fields */ + mailimf_fields_fields_init(&single_fields, fields); + /* do the things */ + mailimf_fields_free(fields); + + return 0; +} + + _________________________________________________________________ + +Parser functions + +mailimf_address_list_parse + +int +mailimf_address_list_parse(char * message, size_t length, + size_t * index, + struct mailimf_address_list ** result); + + + mailimf_address_list_parse() parse a list of addresses in RFC 2822 + form. + + * message this is a string containing the list of addresses. + * length this is the size of the given string + * index this is a pointer to the start of the list of addresses in + the given string, (* index) is modified to point at the end of the + parsed data. + * result the result of the parse operation is stored in (* result) + (see the Section called mailimf_address_list - list of addresses). + + return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error. + + Example 3-33. parsing a list of addresses +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_address_list * addr_list; + size_t current_index; + + current_index = 0; + r = mailimf_address_list_parse(mem, stat_info.st_size, + ¤t_index, &addr_list); + if (r == MAILIMF_NO_ERROR) { + display_address_list(addr_list); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_address_list_free(addr_list); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailimf_address_parse + +#include <libetpan/libetpan.h> + +int +mailimf_address_parse(char * message, size_t length, + size_t * index, + struct mailimf_address ** result); + + + mailimf_address_parse() parse an address in RFC 2822 form. + + * message this is a string containing the address. + * length this is the size of the given string. + * index index this is a pointer to the start of the address in the + given string, (* index) is modified to point at the end of the + parsed data. + * result the result of the parse operation is stored in (* result) + (see the Section called mailimf_address - address). + + return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error. + + Example 3-34. parsing an address +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_address * addr; + size_t current_index; + + current_index = 0; + r = mailimf_address_parse(mem, stat_info.st_size, + ¤t_index, &addr); + if (r == MAILIMF_NO_ERROR) { + display_address(addr); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_address_free(addr); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailimf_body_parse + +#include <libetpan/libetpan.h> + +int mailimf_body_parse(char * message, size_t length, + size_t * index, + struct mailimf_body ** result); + + + mailimf_body_parse() parse text body of a message. + + * message this is a string containing the message body part. + * length this is the size of the given string. + * index this is a pointer to the start of the message text part in + the given string, (* index) is modified to point at the end of the + parsed data. + * result the result of the parse operation is stored in (* result) + (see the Section called mailimf_body - message body without + headers). + + return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error. + + Example 3-35. parsing a message body +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_body * b; + struct mailimf_fields * f; + size_t current_index; + size_t size; + + size = stat_info.st_size; + current_index = 0; + r = mailimf_fields_parse(mem, size, ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + r = mailimf_crlf_parse(mem, size, ¤t_index); + /* ignore parse error of crlf */ + + r = mailimf_body_parse(mem, size, ¤t_index, &b); + if (r == MAILIMF_NO_ERROR) { + + display_body(b); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_body_free(b); + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailimf_envelope_and_optional_fields_parse + +#include <libetpan/libetpan.h> + +int +mailimf_envelope_and_optional_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + + + mailimf_envelope_and_optional_fields_parse() returns a list of most + useful headers (parsed). The other headers will be placed in the list + in a non-parsed form. + + * message this is a string containing the header. + * length this is the size of the given string + * index index this is a pointer to the start of the header in the + given string, (* index) is modified to point at the end of the + parsed data + * result the result of the parse operation is stored in (* result) + (see the Section called mailimf_fields - list of header fields). + + return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error. + + Example 3-36. parsing commonly used fields and return other fields in + a non-parsed form +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_envelope_and_optional_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailimf_envelope_fields_parse + +#include <libetpan/libetpan.h> + +int mailimf_envelope_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + + + mailimf_envelope_fields_parse() return a list of most useful headers + (parsed). + + * message this is a string containing the header + * length this is the size of the given string + * index index this is a pointer to the start of the header in the + given string, (* index) is modified to point at the end of the + parsed data + * result the result of the parse operation is stored in (* result) + (see the Section called mailimf_fields - list of header fields). + + return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error. + + Example 3-37. parsing commonly used fields +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_envelope_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailimf_optional_fields_parse + +#include <libetpan/libetpan.h> + +int +mailimf_optional_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + + + mailimf_optional_fields_parse return a list of non-parsed headers. + + * message this is a string containing the header + * length this is the size of the given string + * index index this is a pointer to the start of the header in the + given string, (* index) is modified to point at the end of the + parsed data + * result the result of the parse operation is stored in (* result) + (see the Section called mailimf_fields - list of header fields). + + return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error. + + Example 3-38. parsing optional fields +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_optional_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailimf_fields_parse + +#include <libetpan/libetpan.h> + +int mailimf_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + + + mailimf_fields_parse() parse headers of a message. + + * message this is a string containing the header + * length this is the size of the given string + * index index this is a pointer to the start of the header in the + given string, (* index) is modified to point at the end of the + parsed data + * result the result of the parse operation is stored in (* result) + (see the Section called mailimf_fields - list of header fields). + + return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error. + + Example 3-39. parsing header fields +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(f); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailimf_ignore_field_parse + +#include <libetpan/libetpan.h> + +int mailimf_ignore_field_parse(char * message, size_t length, + size_t * index); + + + mailimf_ignore_field_parse() skip the next header. + + * message this is a string containing the header + * length this is the size of the given string + * index index this is a pointer to the start of the field to skip in + the given string, (* index) is modified to point at the end of the + parsed data + + return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error. + + Example 3-40. skipping fields +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + size_t current_index; + + current_index = 0; + r = mailimf_ignore_field_parse(mem, stat_info.st_size, + ¤t_index); + if (r == MAILIMF_NO_ERROR) { + /* do the things */ + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailimf_mailbox_list_parse + +#include <libetpan/libetpan.h> + +int +mailimf_mailbox_list_parse(char * message, size_t length, + size_t * index, + struct mailimf_mailbox_list ** result); + + + mailimf_mailbox_list_parse() parse a list of mailboxes in RFC 2822 + form. + + * message this is a string containing the list of mailboxes. + * length this is the size of the given string. + * index index this is a pointer to the start of the list of + mailboxes in the given string, (* index) is modified to point at + the end of the parsed data. + * result the result of the parse operation is stored in (* result). + (see the Section called mailimf_mailbox_list - list of mailboxes) + + return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error. + + Example 3-41. parsing a list of mailboxes +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_mailbox_list * mb_list; + size_t current_index; + + current_index = 0; + r = mailimf_mailbox_list_parse(mem, stat_info.st_size, + ¤t_index, &mb_list); + if (r == MAILIMF_NO_ERROR) { + display_mailbox_list(mb_list); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_mailbox_list_free(mb_list); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailimf_mailbox_parse + + +#include <libetpan/libetpan.h> + +int mailimf_mailbox_parse(char * message, size_t length, + size_t * index, + struct mailimf_mailbox ** result); + + + mailimf_mailbox_parse parse a mailbox in RFC 2822 form. + + * message this is a string containing the mailbox. + * length this is the size of the given string. + * index index this is a pointer to the start of the mailbox in the + given string, (* index) is modified to point at the end of the + parsed data. + * result the result of the parse operation is stored in (* result). + (see the Section called mailimf_mailbox - mailbox) + + return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error. + + Example 3-42. parsing a mailbox +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_mailbox_list * mb_list; + size_t current_index; + + current_index = 0; + r = mailimf_mailbox_parse(mem, stat_info.st_size, + ¤t_index, &mb_list); + if (r == MAILIMF_NO_ERROR) { + display_mailbox_list(mb_list); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_mailbox_free(mb_list); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailimf_message_parse + +#include <libetpan/libetpan.h> + +int mailimf_message_parse(char * message, size_t length, + size_t * index, + struct mailimf_message ** result); + + + mailimf_message_parse parse message (headers and body). + + * message this is a string containing the message content. + * param length this is the size of the given string. + * param index this is a pointer to the start of the message in the + given string, (* index) is modified to point at the end of the + parsed data. + * param result the result of the parse operation is stored in (* + result) (see the Section called mailimf_message - parsed message). + + Example 3-43. parsing a message +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_message * m; + size_t current_index; + + current_index = 0; + r = mailimf_message_parse(mem, stat_info.st_size, + ¤t_index, &m); + if (r == MAILIMF_NO_ERROR) { + display_message(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_message_free(m); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +Creation functions + +mailimf_mailbox_list + +#include <libetpan/libetpan.h> + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new_empty(); + +int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list, + struct mailimf_mailbox * mb); + +int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list, + char * mb_str); + +int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list, + char * display_name, char * address); + + + mailimf_mailbox_list_new_empty() creates a new empty list of + mailboxes. + + mailimf_mailbox_list_add adds a mailbox to the list of mailboxes. + + mailimf_mailbox_list_add_parse adds a mailbox given in form of a + string to the list of mailboxes. + + mailimf_mailbox_list_add_mb adds a mailbox given in form of a couple : + display name, mailbox address. + + * mailbox_list is the list of mailboxes. + * mb is a mailbox (see the Section called mailimf_mailbox - + mailbox). + * mb_str is a mailbox given in the form of a string. + * display_name is the display name. + * address is the mailbox address. + + Example 3-44. creating a list of mailboxes +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_mailbox * mb; + + mb_list = mailimf_mailbox_list_new_empty(); + + mb = mailimf_mailbox_new(strdup("DINH Viet Hoa"), + strdup("dinh.viet.hoa@free.fr")); + mailimf_mailbox_list_add(mb_list, mb); + + mailimf_mailbox_list_add_parse(mb_list, "foo bar <foo@bar.org>"); + + mailimf_mailbox_list_add_mb(mb_list, strdup("bar foo"), strdup("bar@foo.com") +); + + mailimf_mailbox_list_free(mb_list); +} + + _________________________________________________________________ + +mailimf_address_list + +#include <libetpan/libetpan.h> + +struct mailimf_address_list * mailimf_address_list_new_empty(); + +int mailimf_address_list_add(struct mailimf_address_list * address_list, + struct mailimf_address * addr); + +int mailimf_address_list_add_parse(struct mailimf_address_list * address_list, + char * addr_str); + +int mailimf_address_list_add_mb(struct mailimf_address_list * address_list, + char * display_name, char * address); + + + mailimf_address_list_new_empty() creates a new empty list of + addresses. + + mailimf_address_list_add adds an address to the list of addresses. + + mailimf_address_list_add_parse adds an address given in form of a + string to the list of addresses. + + mailimf_address_list_add_mb adds a mailbox given in form of a couple : + display name, mailbox address. + + * address_list is the list of mailboxes. + * addr is an address. (see the Section called mailimf_address - + address). + * addr_str is an address given in the form of a string. + * display_name is the display name. + * address is the mailbox address. + _________________________________________________________________ + +mailimf_fields + +#include <libetpan/libetpan.h> + +struct mailimf_fields * +mailimf_fields_new_empty(void); + +struct mailimf_field * mailimf_field_new_custom(char * name, char * value); + +int mailimf_fields_add(struct mailimf_fields * fields, + struct mailimf_field * field); + +int mailimf_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * msg_id, + clist * in_reply_to, + clist * references, + char * subject); + +struct mailimf_fields * +mailimf_fields_new_with_data_all(struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * message_id, + clist * in_reply_to, + clist * references, + char * subject); + +struct mailimf_fields * +mailimf_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + clist * in_reply_to, + clist * references, + char * subject); + +char * mailimf_get_message_id(void); + +struct mailimf_date_time * mailimf_get_current_date(void); + +int +mailimf_resent_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * resent_date, + struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +struct mailimf_fields * +mailimf_resent_fields_new_with_data_all(struct mailimf_date_time * + resent_date, struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +struct mailimf_fields * +mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc); + + + * from is the parsed content of the From field (see the Section + called mailimf_from - parsed content of From header). + * sender is the parsed content of the Sender field (see the Section + called mailimf_sender - parsed content of Sender header). + * reply_to is the parsed content of the Reply-To field (see the + Section called mailimf_reply_to - parsed content of Reply-To + header). + * to is the parsed content of the To field (see the Section called + mailimf_to - parsed content of To header). + * cc is the parsed content of the Cc field (see the Section called + mailimf_cc - parsed content of Cc). + * bcc is the parsed content of the Bcc field (see the Section called + mailimf_bcc - parsed content of Bcc field). + * message_id is the parsed content of the Message-ID field (see the + Section called mailimf_message_id - parsed content of Message-ID + header). + * in_reply_to is the parsed content of the In-Reply-To field (see + the Section called mailimf_in_reply_to - parsed content of + In-Reply-To field). + * references is the parsed content of the References field (see the + Section called mailimf_references - parsed content of References + field). + * subject is the content of the Subject field (see the Section + called mailimf_subject - parsed content of Subject field). + * resent_date is the parsed content of the Resent-Date field (see + the Section called mailimf_orig_date - parsed content of date + header). + * resent_from is the parsed content of the Resent-From field (see + the Section called mailimf_from - parsed content of From header). + * resent_sender is the parsed content of the Resent-Sender field + (see the Section called mailimf_sender - parsed content of Sender + header). + * resent_to is the parsed content of the Resent-To field (see the + Section called mailimf_to - parsed content of To header). + * resent_cc is the parsed content of the Resent-Cc field (see the + Section called mailimf_cc - parsed content of Cc). + * resent_bcc is the parsed content of the Resent-Bcc field (see the + Section called mailimf_bcc - parsed content of Bcc field). + * resent_msg_id is the parsed content of the Resent-Message-ID field + (see the Section called mailimf_message_id - parsed content of + Message-ID header). + + mailimf_fields_new_empty() creates a new empty set of headers. + + mailimf_field_new_custom() creates a new custom header. + + mailimf_fields_add() adds a header to the set of headers. + + mailimf_fields_add_data() adds some headers to the set of headers. + + mailimf_fields_new_with_data_all() creates a set of headers with some + headers (including Date and Message-ID). + + mailimf_fields_new_with_data() creates a set of headers with some + headers (Date and Message-ID will be generated). + + mailimf_get_message_id() generates a Message-ID. The result must be + freed using free(). + + mailimf_get_current_date() generates a Date. The result must be freed + using mailimf_date_time_free. + + mailimf_resent_fields_add_data() adds some resent headers to the set + of headers. + + mailimf_resent_fields_new_with_data_all() creates a set of headers + with some resent headers (including Resent-Date and + Resent-Message-ID). + + mailimf_resent_fields_new_with_data() creates a set of headers with + some resent headers (Resent-Date and Resent-Message-ID will be + generated) + + Example 3-45. creation of header fields +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_field * field; + struct mailimf_date_time * date; + char * msg_id; + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + + fields = mailimf_fields_new_empty(); + field = mailimf_field_new_custom(strdup("X-Mailer"), strdup("my-mailer")); + mailimf_fields_add(fields, field); + + from = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet. +hoa@free.fr"); + date = mailimf_get_current_date(); + msg_id = mailimf_get_message_id(); + to = mailimf_address_list_new_empty(); + mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org"); + + mailimf_fields_add_data(fields, date, from, NULL, NULL, to, NULL, NULL, + msg_id, NULL, NULL, strdup("hello")); + + /* do the things */ + + mailimf_fields_free(fields); +} + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + struct mailimf_date_time * date; + char * msg_id; + + from = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet. +hoa@free.fr"); + to = mailimf_address_list_new_empty(); + mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org"); + date = mailimf_get_current_date(); + msg_id = mailimf_get_message_id(); + + fields = mailimf_fields_new_with_all_data(date, from, NULL, NULL, to, NULL, N +ULL, + msg_id, NULL, NULL, strdup("hello")); + + /* do the things */ + + mailimf_fields_free(fields); +} + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + + from = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet. +hoa@free.fr"); + to = mailimf_address_list_new_empty(); + mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org"); + + fields = mailimf_fields_new_with_data(from, NULL, NULL, to, NULL, NULL, + NULL, NULL, strdup("hello")); + + /* do the things */ + + mailimf_fields_free(fields); +} + + _________________________________________________________________ + +Rendering of messages + +Header fields + +#include <libetpan/libetpan.h> + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field); + + + * col current column is given for wrapping purpose in (* col), the + resulting columns will be returned.. + * f is the file descriptor. It can be stdout for example. + * fields is the header fields (see the Section called mailimf_fields + - list of header fields). + * field is a field (see the Section called mailimf_field - header + field). + + mailimf_fields_write outputs the set of header fields. + + mailimf_envelope_fields_write outputs the set of header fields except + the optional fields. + + mailimf_field_write outputs a header. + + Example 3-46. rendering of fields +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + int col; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_imf_fields(); + + col = 0; + mailimf_fields_write(stdout, &col, fields); + + mailimf_fields_free(fields); +} + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + int col; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_imf_fields(); + + col = 0; + mailimf_envelope_fields_write(stdout, &col, fields); + + mailimf_fields_free(fields); +} + +int main(int argc, char ** argv) +{ + struct mailimf_field * field; + int col; + + field = mailimf_field_new_custom(strdup("X-Mailer"), strdup("my mailer")); + + col = 0; + mailimf_field_write(stdout, &col, field); + + mailimf_field_free(field); +} + + _________________________________________________________________ + +Chapter 4. MIME + + libEtPan! implements a MIME message parser (also known as messages + with attachments or multipart messages). This also allows to generate + MIME messages. + + Warning + + All allocation functions will take as argument allocated data and will + store these data in the structure they will allocate. Data should be + persistant during all the use of the structure and will be freed by + the free function of the structure + + allocation functions will return NULL on failure functions returning + integer will be returning one of the following error code: + MAILIMF_NO_ERROR, MAILIMF_ERROR_PARSE, MAILIMF_ERROR_MEMORY, + MAILIMF_ERROR_INVAL, or MAILIMF_ERROR_FILE. + _________________________________________________________________ + +Quick start + + You will need this module when you want to parse a MIME message. + _________________________________________________________________ + +Parse MIME message + + You will use the following function : + + * mailmime_parse (the Section called + mailimf_envelope_and_optional_fields_parse in Chapter 3) + _________________________________________________________________ + +Render the MIME message + + Build your MIME message, then use mailmime_write (the Section called + mailmime_write) to render a MIME message. + _________________________________________________________________ + +Data types + +mailmime_composite_type - Composite MIME type + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_COMPOSITE_TYPE_ERROR, + MAILMIME_COMPOSITE_TYPE_MESSAGE, + MAILMIME_COMPOSITE_TYPE_MULTIPART, + MAILMIME_COMPOSITE_TYPE_EXTENSION +}; + +struct mailmime_composite_type { + int ct_type; + char * ct_token; +}; + +struct mailmime_composite_type * +mailmime_composite_type_new(int ct_type, char * ct_token); + +void mailmime_composite_type_free(struct mailmime_composite_type * ct); + + + This is a MIME composite type such as message or multipart. + + ct_type can have one of the 3 following values : + MAILMIME_COMPOSITE_TYPE_MESSAGE when the composite MIME type is + message, MAILMIME_COMPOSITE_TYPE_MULTIPART when the composite MIME + type is multipart, MAILMIME_COMPOSITE_TYPE_EXTENSION for other and + ct_token is set in this case. MAILMIME_COMPOSITE_TYPE_ERROR is used + internally on parse error. + + mailmime_composite_type_new() creates and initializes a data structure + with a value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + + mailmime_composite_type_free() frees memory used by the structure and + substructures will also be released. + + Example 4-1. create and display MIME composite type +#include <libetpan/libetpan.h> + +int main(void) +{ + struct mailmime_composite_type * ct; + + ct = mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL); + + /* do your things ... */ + + mailmime_composite_type_free(ct); + + exit(EXIT_SUCCESS); +} + +void display_composite_type() +{ + switch (ct->type) { + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + printf("composite type is message\n"); + break; + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + printf("composite type is multipart\n"); + break; + case MAILMIME_COMPOSITE_TYPE_EXTENSION: + printf("composite type: %s\n", ct->ct_token); + break; + } +} + + _________________________________________________________________ + +mailmime_content - MIME content type (Content-Type) + +#include <libetpan/libetpan.h> + +struct mailmime_content { + struct mailmime_type * ct_type; + char * ct_subtype; + clist * ct_parameters; /* elements are (struct mailmime_parameter *) */ +}; + +struct mailmime_content * +mailmime_content_new(struct mailmime_type * ct_type, + char * ct_subtype, + clist * ct_parameters); + +void mailmime_content_free(struct mailmime_content * content); + + + This is a MIME content type such as message/rfc822 or text/plain. + + * ct_type is the main MIME type, for example text in plain/text (see + the Section called mailmime_type - MIME main type). + ct_subtype is the MIME subtype, for example plain in plain/text. + * ct_parameters is the list of parameters for the given MIME type. + For example, for plain/text, we can find charset=iso-8859-1, + format=flowed. Each element of the list if of type struct + mailmime_parameter * (see the Section called mailmime_parameter - + MIME type parameter). + + mailmime_content_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailmime_content_free() frees memory used by the structure and + substructures will also be released. + + Example 4-2. Creation and display of MIME content type +#include <libetpan/libetpan.h> + +int main(void) +{ + struct mailmime_content * content; + struct mailmime_type * type; + struct mailmime_discrete_type * dt; + struct mailmime_parameter * param; + clist * param_list; + + dt = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, NULL); + type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, dt, NUL); + param_list = clist_new(); + param = mailmime_parameter_new(strdup("charset"), strdup("iso-8859-1")); + clist_append(param_list, param); + + content = mailmime_content_new(type, strdup("plain"), param_list); + + /* do your things */ + + exit(EXIT_SUCCESS); +} + +void display_mime_content(struct mailmime_content * content_type) +{ + clistiter * cur; + + printf("type:\n"); + display_type(content_type->ct_type); + printf("\n"); + printf("subtype: %s\n", content_type->ct_subtype); + printf("\n"); + + for(cur = clist_begin(content_type->ct_parameters) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + display_mime_parameter(param); + printf("\n"); + } + printf("\n"); +} + + _________________________________________________________________ + +mailmime_discrete_type - MIME discrete type + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISCRETE_TYPE_ERROR, + MAILMIME_DISCRETE_TYPE_TEXT, + MAILMIME_DISCRETE_TYPE_IMAGE, + MAILMIME_DISCRETE_TYPE_AUDIO, + MAILMIME_DISCRETE_TYPE_VIDEO, + MAILMIME_DISCRETE_TYPE_APPLICATION, + MAILMIME_DISCRETE_TYPE_EXTENSION +}; + +struct mailmime_discrete_type { + int dt_type; + char * dt_extension; +}; + +struct mailmime_discrete_type * +mailmime_discrete_type_new(int dt_type, char * dt_extension); + +void mailmime_discrete_type_free(struct mailmime_discrete_type * + discrete_type); + + + This is a MIME discrete type such as text or image. This is also known + as single part. This kind of part does not have any child. + + dt_type is one of the given values : MAILMIME_DISCRETE_TYPE_TEXT if + part is text, MAILMIME_DISCRETE_TYPE_IMAGE if part is an image, + MAILMIME_DISCRETE_TYPE_AUDIO if part is audio data, + MAILMIME_DISCRETE_TYPE_VIDEO if part is video, + MAILMIME_DISCRETE_TYPE_APPLICATION if part is application data or + MAILMIME_DISCRETE_TYPE_EXTENSION for other. In the case of + MAILMIME_DISCRETE_TYPE_EXTENSION, dt_extension is filled in. + MAILMIME_DISCRETE_TYPE_ERROR is used internally. + + mailmime_discrete_type_new() creates and initializes a data structure + with a value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + + mailmime_discrete_type_free() frees memory used by the structure and + substructures will also be released. + + Example 4-3. Creation and display of MIME discrete type +#include <libetpan/libetpan.h> + +/* standard type */ + +int main(int argc, char ** argv) +{ + struct mailmime_discrete_type * discrete_type; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, + NULL); + + /* do the things */ + + mailmime_discrete_type_free(discrete_type); +} + +/* extension */ + +int main(int argc, char ** argv) +{ + struct mailmime_discrete_type * discrete_type; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_EXTENSION, + strdup("my-type")); + + /* do the things */ + + mailmime_discrete_type_free(discrete_type); +} + +void display_mime_discrete_type(struct mailmime_discrete_type * discrete_type) +{ + switch (discrete_type->dt_type) { + case MAILMIME_DISCRETE_TYPE_TEXT: + printf("text\n"); + break; + case MAILMIME_DISCRETE_TYPE_IMAGE: + printf("image\n"); + break; + case MAILMIME_DISCRETE_TYPE_AUDIO: + printf("audio\n"); + break; + case MAILMIME_DISCRETE_TYPE_VIDEO: + printf("video\n"); + break; + case MAILMIME_DISCRETE_TYPE_APPLICATION: + printf("application\n"); + break; + case MAILMIME_DISCRETE_TYPE_EXTENSION: + printf("extension : %s\n", discrete_type->dt_extension); + break; + } +} + + _________________________________________________________________ + +mailmime_field - MIME header field + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_FIELD_NONE, + MAILMIME_FIELD_TYPE, + MAILMIME_FIELD_TRANSFER_ENCODING, + MAILMIME_FIELD_ID, + MAILMIME_FIELD_DESCRIPTION, + MAILMIME_FIELD_VERSION, + MAILMIME_FIELD_DISPOSITION, + MAILMIME_FIELD_LANGUAGE, +}; + +struct mailmime_field { + int fld_type; + union { + struct mailmime_content * fld_content; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + struct mailmime_language * fld_language; + } fld_data; +}; + +struct mailmime_field * +mailmime_field_new(int fld_type, + struct mailmime_content * fld_content, + struct mailmime_mechanism * fld_encoding, + char * fld_id, + char * fld_description, + uint32_t fld_version, + struct mailmime_disposition * fld_disposition, + struct mailmime_language * fld_language); + +void mailmime_field_free(struct mailmime_field * field); + + + This is a parsed MIME header field; + + * fld_type is the type of MIME header field. The value can be + MAILMIME_FIELD_TYPE if field is Content-Type, + MAILMIME_FIELD_TRANSFER_ENCODING if field is + Content-Transfer-Encoding, MAILMIME_FIELD_ID if field is + Content-ID, MAILMIME_FIELD_DESCRIPTION if field is + Content-Description, MAILMIME_FIELD_VERSION if field is + MIME-Version, MAILMIME_FIELD_DISPOSITION if field is + Content-Disposition or MAILMIME_FIELD_LANGUAGE if field is + Content-Language. MAILMIME_FIELD_NONE is used internally. + * fld_data.fld_content is set in case of Content-Type. (see the + Section called mailmime_content - MIME content type + (Content-Type)). + * fld_data.fld_encoding is set in case of Content-Transfer-Encoding. + (see the Section called mailmime_mechanism - MIME transfer + encoding mechanism (Content-Transfer-Encoding)). + * fld_data.fld_id is set in case of Content-ID. This is a string. + * fld_data.fld_description is set in case of Content-Description. + This is a string. + * fld_data.fld_version is set in case of MIME-Version. This is an + integer built using the following formula : fld_version = major * + 2^16 + minor. Currenly MIME-Version is always 1.0, this means that + fld_version will always be 2^16 (in C language, this is 1 << 16). + * fld_data.fld_disposition is set in case of Content-Disposition. + (see the Section called mailmime_disposition - MIME disposition + information (Content-Disposition)). + * fld_data.fld_language is set in case of Content-Language. (see the + Section called mailmime_language - Language of MIME part). + + mailmime_field_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailmime_field_free() frees memory used by the structure and + substructures will also be released. + + Example 4-4. Creation and display of MIME header field +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_field * field; + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL); + + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, encoding, NULL, NULL, 0, NULL, NULL); + + /* do the things */ + + mailmime_field_free(field); +} + +void display_mime_field(struct mailmime_field * field) +{ + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + printf("content-type:"); + display_mime_content(field->fld_data.fld_content); + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + printf("content-transfer-encoding:"); + display_mime_mechanism(field->fld_data.fld_encoding); + break; + case MAILMIME_FIELD_ID: + printf("content-id: %s\n", field->fld_data.fld_id); + break; + case MAILMIME_FIELD_DESCRIPTION: + printf("content-description: %s\n", field->fld_data.fld_description); + break; + case MAILMIME_FIELD_VERSION: + printf("mime-version: %i.%i\n", + field->version>> 16, field->fld_data.fld_version & 0xFFFF); + break; + case MAILMIME_FIELD_DISPOSITION: + printf("content-disposition:"); + display_mime_disposition(field->fld_data.fld_disposition); + break; + case MAILMIME_FIELD_LANGUAGE: + printf("content-language:"); + display_mime_language(field->fld_data.fld_language); + break; + } +} + + _________________________________________________________________ + +mailmime_mechanism - MIME transfer encoding mechanism +(Content-Transfer-Encoding) + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_mechanism { + int enc_type; + char * enc_token; +}; + +struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_tok +en); + +void mailmime_mechanism_free(struct mailmime_mechanism * mechanism); + + + This is a MIME transfer encoding mechanism description. + + enc_type is an encoding type. The value of this field can be + MAILMIME_MECHANISM_7BIT if mechanism is 7bit, MAILMIME_MECHANISM_8BIT + if mechanism is 8bit, MAILMIME_MECHANISM_BINARY if mechanism is + binary, MAILMIME_MECHANISM_QUOTED_PRINTABLE if mechanism is + quoted-printable, MAILMIME_MECHANISM_BASE64 if mechanism is base64 or + MAILMIME_MECHANISM_TOKEN for other. In case of + MAILMIME_MECHANISM_TOKEN, field enc_token is filled in. + MAILMIME_MECHANISM_ERROR is used internally. + + mailmime_mechanism_new() creates and initializes a data structure with + a value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailmime_mechanism_free() frees memory used by the structure and + substructures will also be released. + + Example 4-5. Creation and display of MIME transfer encoding mechanism +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_QUOTED_PRINTABLE, NULL); + + /* do the things */ + + mailmime_mechanism_free(encoding); +} + +int main(int argc, char ** argv) +{ + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_TOKEN, + strdup("uuencoding")); + + /* do the things */ + + mailmime_mechanism_free(encoding); +} + +void display_mime_mechanism(struct mailmime_mechanism * encoding) +{ + switch (encoding->enc_type) { + case MAILMIME_MECHANISM_7BIT: + printf("7bit\n"); + break; + case MAILMIME_MECHANISM_8BIT: + printf("8bit\n"); + break; + case MAILMIME_MECHANISM_BINARY: + printf("binary\n"); + break; + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + printf("quoted-printable\n"); + break; + case MAILMIME_MECHANISM_BASE64: + printf("base64\n"); + break; + case MAILMIME_MECHANISM_TOKEN: + printf("extension : %s\n", encoding->enc_token); + break; + } +} + + _________________________________________________________________ + +mailmime_fields - header fields + +#include <libetpan/libetpan.h> + +struct mailmime_fields { + clist * fld_list; /* list of (struct mailmime_field *) */ +}; + +struct mailmime_fields * mailmime_fields_new(clist * fld_list); + +void mailmime_fields_free(struct mailmime_fields * fields); + + + This is the header fields of a MIME part. + + fld_list is the list of the header fields. Each element of the list is + a mailmime_field (See the Section called mailmime_field - MIME header + field). + + mailmime_fields_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailmime_fields_free() frees memory used by the structure and + substructures will also be released. + + Example 4-6. Creation and display of MIME fields +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_field * field; + struct mailmime_fields * fields; + clist * list; + struct mailmime_mechanism * encoding; + struct mailmime_disposition * disposition; + + list = clist_new(); + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL); + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, encoding, NULL, NULL, 0, NULL, NULL); + clist_append(list, field); + + field = mailmime_field_new(MAILMIME_FIELD_VERSION, + NULL, NULL, NULL, NULL, 1 << 16, NULL, NULL); + clist_append(list, field); + + /* look at the example in mailmime_disposition to see how to + build a mailmime_disposition */ + disposition = build_mime_disposition(); + field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION, + NULL, NULL, NULL, NULL, 0, disposition, NULL); + clist_append(list, field); + + fields = mailmime_fields_new(list); + + /* do the things */ + + mailmime_fields_free(fields); +} + +void display_mime_fields(struct mailmime_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + display_field(field); + } +} + + _________________________________________________________________ + +mailmime_parameter - MIME type parameter + +struct mailmime_parameter { + char * pa_name; + char * pa_value; +}; + + + This is the MIME type parameter in Content-Type MIME header field. For + example, this can be charset="iso-8859-1". + + * pa_name is the name of the parameter, for example : charset. + * pa_value is the value of the parameter, for example : iso-8859-1. + + mailmime_parameter_new() creates and initializes a data structure with + a value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailmime_parameter_free() frees memory used by the structure and + substructures will also be released. + + Example 4-7. Creation and display of MIME type parameter +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_parameter * param; + + param = mailmime_parameter_new(strdup("charset"), strdup("iso-8859-1")); + + /* do the things */ + + mailmime_parameter_free(param); +} + +void display_mime_parameter(struct mailmime_parameter * param) +{ + printf("%s = %s\n", param->pa_name, param->pa_value); +} + + _________________________________________________________________ + +mailmime_type - MIME main type + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_TYPE_ERROR, + MAILMIME_TYPE_DISCRETE_TYPE, + MAILMIME_TYPE_COMPOSITE_TYPE +}; + +struct mailmime_type { + int tp_type; + union { + struct mailmime_discrete_type * tp_discrete_type; + struct mailmime_composite_type * tp_composite_type; + } tp_data; +}; + +struct mailmime_type * +mailmime_type_new(int tp_type, + struct mailmime_discrete_type * tp_discrete_type, + struct mailmime_composite_type * tp_composite_type); + +void mailmime_type_free(struct mailmime_type * type); + + + This is the MIME main type (no subtype, no parameter). + + * tp_type. The value of this field is either + MAILMIME_TYPE_DISCRETE_TYPE for MIME discrete type, or + MAILMIME_TYPE_COMPOSITE_TYPE for MIME composite type. + MAILMIME_TYPE_ERROR is used internally. + * tp_data.tp_discrete_type is set when tp_type is + MAILMIME_TYPE_DISCRETE_TYPE (see the Section called + mailmime_discrete_type - MIME discrete type). + * tp_data.tp_composite_type is set when tp_type is + MAILMIME_TYPE_COMPOSITE_TYPE (see the Section called + mailmime_composite_type - Composite MIME type). + + mailmime_discrete_type_new() creates and initializes a data structure + with a value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + + mailmime_discrete_type_free() frees memory used by the structure and + substructures will also be released. + + Example 4-8. Creation and display of MIME main type +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_type * type; + struct mailmime_discrete_type * discrete_type; + + discrete_type = + mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, NULL); + type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, discrete_type, NULL); + + /* do the things */ + + mailmime_type_free(type); +} + +int main(int argc, char ** argv) +{ + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, composite_type); + + /* do the things */ + + mailmime_type_free(type); +} + +void display_mime_type(struct mailmime_type * type) +{ + printf("mime type:\n"); + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + printf("discrete type:\n"); + display_mime_discrete_type(type->tp_data.tp_discrete_type); + break; + case MAILMIME_TYPE_COMPOSITE_TYPE: + printf("composite type:\n"); + display_mime_composite_type(type->tp_data.tp_composite_type); + break; + } + printf("\n"); +} + + _________________________________________________________________ + +mailmime_language - Language of MIME part + +#include <libetpan/libetpan.h> + +struct mailmime_language { + clist * lg_list; /* atom (char *) */ +}; + +struct mailmime_language * mailmime_language_new(clist * lg_list); + +void mailmime_language_free(struct mailmime_language * lang); + + + This is the language used in the MIME part. + + lg_list is the list of codes of languages used in the MIME part. This + is a list of strings. + + mailmime_language_new() creates and initializes a data structure with + a value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailmime_language_free() frees memory used by the structure and + substructures will also be released. + + Example 4-9. Creation and display of language of MIME part +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_language * language; + clist * list; + + list = clist_new(); + + clist_append(list, strdup("fr")); + clist_append(list, strdup("en")); + + language = mailmime_language_new(list); + + /* do the things */ + + mailmime_language_free(language); +} + +void display_mime_language(struct mailmime_language * language) +{ + clistiter * cur; + + printf("languages: "); + for(cur = clist_begin(language->lg_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * name; + + name = clist_content(cur); + printf("%s ", name); + } + printf("\n"); +} + + _________________________________________________________________ + +mailmime_data - Content of MIME part + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_DATA_TEXT, + MAILMIME_DATA_FILE, +}; + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_data { + int dt_type; + int dt_encoding; + int dt_encoded; + union { + struct { + const char * dt_data; + size_t dt_length; + } dt_text; + char * dt_filename; + } dt_data; +}; + +struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, + int dt_encoded, const char * dt_data, size_t dt_length, + char * dt_filename); + +void mailmime_data_free(struct mailmime_data * mime_ + + This is the content of MIME part, content of preamble or content of + epilogue. + + dt_type can be MAILMIME_DATA_TEXT if the content is a string in + memory, MAILMIME_DATA_FILE if the content is in a file, + + dt_encoding is the encoding mechanism of the part. The value of this + field can be MAILMIME_MECHANISM_7BIT if mechanism is 7bit, + MAILMIME_MECHANISM_8BIT if mechanism is 8bit, + MAILMIME_MECHANISM_BINARY if mechanism is binary, + MAILMIME_MECHANISM_QUOTED_PRINTABLE if mechanism is quoted-printable, + MAILMIME_MECHANISM_BASE64 if mechanism is base64 or + MAILMIME_MECHANISM_TOKEN for other. If MAILMIME_MECHANISM_TOKEN, the + part will be considered as binary. MAILMIME_MECHANISM_ERROR is used + internally. + + dt_encoded is set to 1 if the part is already encoded with the + mechanism given in dt_encoding. It is set to 0 if the part is already + decoded or if it is necessary to encode that part before rendering it. + + dt_data.dt_text.dt_data is a pointer to the content of the part and + dt_data.dt_text.dt_length is the length of the data if dt_type is + MAILMIME_DATA_TEXT. + + dt_data.dt_filename is the name of the file if dt_type is + MAILMIME_DATA_FILE. + + mailmime_data_new() creates and initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will be freed if the object is released. + + mailmime_data_free() frees memory used by the structure and + substructures will also be released. + + Example 4-10. Creation and display of MIME part content +#include <libetpan/libetpan.h> + +/* build data with a string */ + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_BASE64, + 0, "foo bar", 7, NULL); + + /* do the things */ + + mailmime_data_free(data); +} + +/* build data with a file */ + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_BASE64, + 0, NULL, 0, strdup("foo.txt")); + + /* do the things */ + + mailmime_data_free(data); +} + +void display_mime_data(struct mailmime_data * data) +{ + switch (data->dt_encoding) { + case MAILMIME_MECHANISM_7BIT: + printf("7bit\n"); + break; + case MAILMIME_MECHANISM_8BIT: + printf("8bit\n"); + break; + case MAILMIME_MECHANISM_BINARY: + printf("binary\n"); + break; + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + printf("quoted-printable\n"); + break; + case MAILMIME_MECHANISM_BASE64: + printf("base64\n"); + break; + case MAILMIME_MECHANISM_TOKEN: + printf("other\n"); + break; + } + + if (data->dt_encoded) + printf("already encoded\n"); + else + printf("not encoded\n"); + + switch (data->dt_type) { + MAILMIME_DATA_TEXT: + printf("data : %p %i\n", data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length); + break; + MAILMIME_DATA_FILE, + printf("data (file) : %s\n", data->dt_data.dt_filename); + break; + } +} + + _________________________________________________________________ + +mailmime - MIME part + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_NONE, + MAILMIME_SINGLE, + MAILMIME_MULTIPLE, + MAILMIME_MESSAGE, +}; + +struct mailmime { + /* parent information */ + int mm_parent_type; + struct mailmime * mm_parent; + clistiter * mm_multipart_pos; + + int mm_type; + const char * mm_mime_start; + size_t mm_length; + + struct mailmime_fields * mm_mime_fields; + struct mailmime_content * mm_content_type; + + struct mailmime_data * mm_body; + union { + /* single part */ + struct mailmime_data * mm_single; /* XXX - was body */ + + /* multi-part */ + struct { + struct mailmime_data * mm_preamble; + struct mailmime_data * mm_epilogue; + clist * mm_mp_list; + } mm_multipart; + + /* message */ + struct { + struct mailimf_fields * mm_fields; + struct mailmime * mm_msg_mime; + } mm_message; + + } mm_data; +}; + +struct mailmime * mailmime_new(int mm_type, + const char * mm_mime_start, size_t mm_length, + struct mailmime_fields * mm_mime_fields, + struct mailmime_content * mm_content_type, + struct mailmime_data * mm_body, + struct mailmime_data * mm_preamble, + struct mailmime_data * mm_epilogue, + clist * mm_mp_list, + struct mailimf_fields * mm_fields, + struct mailmime * mm_msg_mime); + +void mailmime_free(struct mailmime * mime); + + + This describes the MIME structure of a message or a subpart of a + message. + _________________________________________________________________ + +common + + * mm_parent_type. MIME part type can be single part, multipart or + message part. This describes the MIME part type of the parent. The + value can be MAILMIME_NONE if there is no parent part, + MAILMIME_SINGLE if parent is a single part, MAILMIME_MULTIPLE if + parent is a multipart, MAILMIME_MESSAGE if parent is a mesage + part. + * mm_parent is the parent MIME structure. + * mm_multipart_pos. In the case the parent is a multipart. This is + the position in the list of children of the parent. This position + is given by a clisiter *. + * mm_type. This describes the MIME part type of this part. The value + can be MAILMIME_SINGLE if this is a single part, MAILMIME_MULTIPLE + if this is a multipart, MAILMIME_MESSAGE if this is a mesage part. + * mm_mime_start. This is used mostly internally. This gives the + beginning of the header of the MIME part, when this is parsed from + a string in memory. + * mm_length. This gives the length of the MIME part, including the + MIME header fields. + * mm_mime_fields is the list of parsed MIME headers of this part. + Content-Type must be excluded and stored in mm_content_type + instead (see the Section called mailmime_fields - header fields). + * mm_content_type is the parsed Content-Type field (see the Section + called mailmime_content - MIME content type (Content-Type)). + * mm_body is the content of the MIME part (excluding MIME header), + when it is parsed from a string in memory (see the Section called + mailmime_data - Content of MIME part). + _________________________________________________________________ + +single part + + * When the part is a single part (mm_type is MAILMIME_SINGLE). The + following fields are valid. + * mm_data.mm_single is the content of the MIME part (excluding MIME + header), when it is parsed from a string in memory. This must have + the same value as mm_body when it is set (see the Section called + mailmime_data - Content of MIME part). + _________________________________________________________________ + +multipart + + * When the part is a multipart (mm_type is MAILMIME_MULTIPLE). The + following fields are valid. + * mm_data.mm_multipart.mm_preamble is the content of the preamble of + the multipart (see the Section called mailmime_data - Content of + MIME part). + * mm_data.mm_multipart.mm_epilogue is the content of the epilogue of + the multipart (see the Section called mailmime_data - Content of + MIME part). + * mm_data.mm_multipart.mm_mp_list is the list of sub parts + _________________________________________________________________ + +message part + + * When the part is a message (mm_type is MAILMIME_MESSAGE). The + following fields are valid. + * mm_data.mm_message.mm_fields is the list of the header fields of + the message (see the Section called mailimf_fields - list of + header fields in Chapter 3). + * mm_data.mm_message.mm_msg_mime is the subpart of the message part. + _________________________________________________________________ + +constructor and destructor + + mailmime_new() creates and initializes a data structure with a value. + Structures given as argument are referenced by the created object and + will be freed if the object is released. + + mailmime_free() frees memory used by the structure and substructures + will also be released. + + Example 4-11. Creation and display of MIME part +#include <libetpan/libetpan.h> + +/* build one single MIME part */ + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + struct mailmime_data * body; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + /* look at the example in mailmime_content to see how to + build a mailmime_content */ + content_type = build_mime_content(); + + body = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + "foo", 3, NULL); + + mime = mailmime_new(MAILMIME_SINGLE, + NULL, 0, fields, mime_fields, content_type, + body, NULL, NULL, NULL, NULL, NULL); + + /* do the things */ + + mailmime_free(mime); +} + +/* build one single MIME part */ + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + char * str; + struct mailmime_data * body; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + /* look at the example in mailmime_content to see how to + build a mailmime_content */ + content_type = build_mime_content(); + + str = malloc(4); + strcpy(str, "foo"); + + body = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + str, 3, NULL); + + mime = mailmime_new(MAILMIME_SINGLE, + NULL, 0, fields, mime_fields, content_type, + body, NULL, NULL, NULL, NULL, NULL); + + /* do the things */ + + mailmime_free(mime); + free(str); +} + +/* build a MIME part with a sub-message */ + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + char * str; + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, + composite_type); + content_type = mailmime_content_new(type, strdup("rfc2822"), NULL); + + /* build_mime_message() is a function that will build a mime message part */ + sub_mime = build_mime_message(); + + mime = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, fields, mime_fields, content_type, + NULL, NULL, NULL, NULL, sub_mime, NULL); + + /* do the things */ + + mailmime_free(mime); +} + +/* build a MIME part with a sub-message (given by a string) */ + + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + char * str; + struct mailmime_data * msg_content; + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, + composite_type); + content_type = mailmime_content_new(type, strdup("rfc2822"), NULL); + + str = malloc(sizeof(SUB_MESSAGE)); + strcpy(str, SUB_MESSAGE); + + msg_content = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, +0, + str, sizeof(SUB_MESSAGE), NULL); + + mime = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, fields, mime_fields, content_type, + NULL, NULL, NULL, NULL, NULL, msg_content); + + /* do the things */ + + mailmime_free(mime); + free(str); +} + +/* build a multipart message */ + + + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + struct mailmime_data * body; + struct mailmime_data * preamble; + struct mailmime_data * epilogue; + clist * list; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, + composite_type); + content_type = mailmime_content_new(type, strdup("mixed"), NULL); + + list = clist_new(); + /* build_mime_message() is a function that will build a mime message part */ + sub_mime = build_mime_message(); + clist_append(list, sub_mime); + sub_mime = build_mime_message(); + clist_append(list, sub_mime); + + preamble = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + PREAMBLE, sizeof(PREAMBLE), NULL); + + epilogue = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + EPILOGUE, sizeof(EPILOGUE), NULL); + + mime = mailmime_new(MAILMIME_SINGLE, + NULL, 0, fields, mime_fields, content_type, + NULL, preamble, epilogue, list, NULL, NULL); + + /* do the things */ + + mailmime_free(mime); +} + +/* display mime part info */ + +void display_mime(struct mailmime * mime) +{ + clistiter * cur; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + printf("single part\n"); + break; + case MAILMIME_MULTIPLE: + printf("multipart\n"); + break; + case MAILMIME_MESSAGE: + printf("message\n"); + break; + } + + printf("part : %p, length : %i\n", + mime->mm_mime_start, mime->mm_length); + printf("\n"); + + if (mime->mm_mime_fields != NULL) { + printf("MIME headers :\n"); + display_mime_fields(mime->mm_mime_fields); + printf("\n"); + } + + printf("content type :\n"); + display_content(mime->mm_content_type); + printf("\n"); + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + display_mime_data(mime->mm_data.mm_single); + break; + + case MAILMIME_MULTIPLE: + if (mime->mm_data.mm_multipart.mm_preamble) { + printf("preamble :\n"); + display_mime_data(mime->mm_data.mm_multipart.mm_preamble); + printf("\n"); + } + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + display_mime(clist_content(cur)); + } + + if (mime->mm_data.mm_multipart.mm_epilogue) { + printf("epilogue :\n"); + display_mime_data(mime->mm_data.mm_multipart.mm_epilogue); + printf("\n"); + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_fields) { + printf("headers :\n"); + display_field(mime->mm_data.mm_message.mm_msg_fields); + printf("\n"); + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + printf("sub message %p :\n", + mime->mm_data.mm_message.mm_msg_mime); + display_mime(mime->mm_data.mm_message.mm_msg_mime); + printf("end of sub message %p\n", + mime->mm_data.mm_message.mm_msg_mime); + } + break; + } +} + + _________________________________________________________________ + +mailmime_disposition - MIME disposition information (Content-Disposition) + +#include <libetpan/libetpan.h> + +struct mailmime_disposition { + struct mailmime_disposition_type * dsp_type; + clist * dsp_parms; /* struct mailmime_disposition_parm */ +}; + + + This is the parsed Content-Disposition header field. + + * dsp_type is the type of disposition (see the Section called + mailmime_disposition_type - Type of MIME disposition). + * dsp_parms is the list of parameters of Content-Disposition header + field. Each element is of type mailmime_disposition_parm (see the + Section called mailmime_disposition_parm - MIME disposition + parameter). + + Example 4-12. Creation and display of MIME disposition information +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_disposition * disposition; + struct mailmime_disposition_type * disposition_type; + clist * disposition_parms; + struct mailmime_disposition_parm * param; + + disposition_type = + mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, NULL); + + disposition_parms = clist_new(); + param = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME, + strdup("foo.txt"), NULL, + NULL, NULL, -1, NULL); + clist_append(disposition_parms, param); + + disposition = mailmime_disposition_new(disposition_type, disposition_parms); + + /* do the things */ + + mailmime_disposition_free(disposition); +} + +void display_mime_disposition(struct mailmime_disposition * disposition) +{ + clistiter * cur; + + printf("disposition type:\n"); + display_mailmime_disposition_type(disposition->dsp_type); + printf("\n"); + printf("disposition parameters:\n"); + for(cur = clist_begin(disposition->dsp_parms) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parm * param; + + param = clist_content(cur); + display_mime_disposition_parm(param); + } + printf("\n"); +} + + + _________________________________________________________________ + +mailmime_disposition_type - Type of MIME disposition + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition_type { + int dsp_type; + char * dsp_extension; +}; + + + This is the type of MIME disposition. Parsed Content-Disposition field + without parameters. + + dsp_type is the type of disposition. The value can be + MAILMIME_DISPOSITION_TYPE_INLINE if MIME disposition is inline, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT if MIME disposition is + attachment, MAILMIME_DISPOSITION_TYPE_EXTENSION for other. In this + case, dsp_extension must be set. MAILMIME_DISPOSITION_TYPE_ERROR is + used internally. + + Example 4-13. Creation and display of MIME disposition type +#include <libetpan/libetpan.h> + +/* standard disposition type */ + +int main(int argc, char ** argv) +{ + struct mailmime_disposition_type * disposition_type; + + disposition_type = + mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, NULL); + + /* do the things */ + + mailmime_disposition_type_free(disposition_type); +} + +/* disposition type extension */ + +int main(int argc, char ** argv) +{ + struct mailmime_disposition_type * disposition_type; + + disposition_type = + mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_EXTENSION, + strdup("mydisposition")); + + /* do the things */ + + mailmime_disposition_type_free(disposition_type); +} + +void display_mime_disposition_type(struct mailmime_disposition_type * dispositi +on_type) +{ + switch (disposition->dsp_type) { + case MAILMIME_DISPOSITION_TYPE_INLINE: + printf("inline\n"); + break; + case MAILMIME_DISPOSITION_TYPE_ATTACHMENT: + printf("attachment\n"); + break; + case MAILMIME_DISPOSITION_TYPE_EXTENSION: + printf("extension : %s\n", disposition_type->dsp_extension); + break; + } +} + + _________________________________________________________________ + +mailmime_disposition_parm - MIME disposition parameter + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISPOSITION_PARM_FILENAME, + MAILMIME_DISPOSITION_PARM_CREATION_DATE, + MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, + MAILMIME_DISPOSITION_PARM_READ_DATE, + MAILMIME_DISPOSITION_PARM_SIZE, + MAILMIME_DISPOSITION_PARM_PARAMETER +}; + +struct mailmime_disposition_parm { + int pa_type; + union { + char * pa_filename; + char * pa_creation_date; + char * pa_modification_date; + char * pa_read_date; + size_t pa_size; + struct mailmime_parameter * pa_parameter; + } pa_data; +}; + + + This is a parameter of MIME disposition information. For example, this + can be filename="foo.jpg". + + * pa_type is the type of disposition. The value can be + MAILMIME_DISPOSITION_PARM_FILENAME for a filename parameter, + MAILMIME_DISPOSITION_PARM_CREATION_DATE for a creation date + parameter, MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE for a + modification date parameter, MAILMIME_DISPOSITION_PARM_READ_DATE + for a last read date parameter, MAILMIME_DISPOSITION_PARM_SIZE for + a file size parameter or MAILMIME_DISPOSITION_PARM_PARAMETER for + other parameters. + * pa_data.pa_filename is the filename parameter when pa_type is + MAILMIME_DISPOSITION_PARM_FILENAME This is a string containing the + name of the file. + * pa_data.pa_creation_date is the creation date parameter when + pa_type is MAILMIME_DISPOSITION_PARM_CREATION_DATE. This is a + string containing the formatted creation date. + * pa_data.pa_modification_date is the modification date parameter + when pa_type is MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE. This + is a string containing the formatted modification date. + * pa_data.pa_read_date is the last read date parameter when pa_type + is MAILMIME_DISPOSITION_PARM_READ_DATE. This is a string + containing the formatted last read date. + * pa_data.pa_size is the size parameter when pa_type is + MAILMIME_DISPOSITION_PARM_SIZE. This gives the size of the file. + * pa_data.pa_parameter is the name and the value of the parameter + when pa_type is MAILMIME_DISPOSITION_PARM_PARAMETER (see the + Section called mailmime_parameter - MIME type parameter) + + Example 4-14. Creation and display of MIME disposition parameter +int main(int argc, char ** argv) +{ + struct mailmime_disposition_parm * param; + + disposition_parms = clist_new(); + param = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME, + strdup("foo.txt"), NULL, + NULL, NULL, -1, NULL); + /* do the things */ + + mailmime_disposition_parm_free(param); +} + +void display_mime_dsp_parm(struct mailmime_disposition_parm * param) +{ + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + printf("filename: %s\n", param->pa_data.pa_filename); + break; + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + printf("creation date: %s\n", param->pa_data.pa_creation_date); + break; + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + printf("modification date: %s\n", param->pa_data.pa_modification_date); + break; + case MAILMIME_DISPOSITION_PARM_READ_DATE: + printf("read date: %s\n", param->pa_data.pa_read_date); + break; + case MAILMIME_DISPOSITION_PARM_SIZE: + printf("size: %lu\n", (unsigned long) param->pa_data.pa_size); + break; + case MAILMIME_DISPOSITION_PARM_PARAMETER: + printf("MIME disposition param:\n"); + display_mime_parameter(param->pa_data.pa_parameter); + break; + } +} + + _________________________________________________________________ + +mailmime_single_fields - MIME headers + +#include <libetpan/libetpan.h> + +struct mailmime_single_fields { + struct mailmime_content * fld_content; + char * fld_content_charset; + char * fld_content_boundary; + char * fld_content_name; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + char * fld_disposition_filename; + char * fld_disposition_creation_date; + char * fld_disposition_modification_date; + char * fld_disposition_read_date; + size_t fld_disposition_size; + struct mailmime_language * fld_language; +}; + +struct mailmime_single_fields * +mailmime_single_fields_new(struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +void mailmime_single_fields_free(struct mailmime_single_fields * + single_fields); + +void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, + struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + + + mailmime_fields (see the Section called mailmime_fields - header + fields) is the native structure that MIME module will use, this module + will provide an easier structure to use when parsing fields. + mailmime_single_fields is an easier structure to get parsed fields, + rather than iteration over the list of fields. + + * fld_content is the MIME content type (see the Section called + mailmime_content - MIME content type (Content-Type)). + * fld_content_charset is the value of the MIME type parameter + charset. + * fld_content_boundary is the value of the MIME type parameter + boundary. + * fld_content_name is the value of the MIME type parameter name. + * fld_encoding is the MIME encoding mechanism used (see the Section + called mailmime_mechanism - MIME transfer encoding mechanism + (Content-Transfer-Encoding)). + * fld_id is the content of the field Content-ID. + * fld_description is the content of the field Content-Description. + * fld_version is the version of MIME in use. + * fld_disposition is the MIME disposition information (see the + Section called mailmime_disposition - MIME disposition information + (Content-Disposition)). + * fld_disposition_filename is the filename parameter of the MIME + disposition information. + * fld_disposition_creation_date is the creation-date parameter of + the MIME disposition information. + * fld_disposition_modification_date is the modification-date + parameter of the MIME disposition information. + * fld_disposition_read_date is the read-date parameter of the MIME + disposition information. + * fld_disposition_size is the size parameter of the MIME disposition + information. + * fld_language is the language of the MIME part (see the Section + called mailmime_language - Language of MIME part). + * single_fields is the structure to fill. + * fld_fields is the MIME fields list to use to fill the + single_fields. + + mailmime_single_fields_new() creates and initializes a data structure + with a value. Structures given as argument are referenced by the + created object and will NOT be freed if the object is released. + + mailmime_single_fields_free() frees memory used by the structure and + substructures will NOT be released. They should be released by the + application. + + mailimf_single_fields_init() will initialize fill the data structure, + using the given argument (fld_fields and fld_content). The interesting + fields will be filled into single_fields. + + Example 4-15. Creation and display of single fields +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_single_fields * single_fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + /* look at the example in mailmime_content to see how to + build a mailmime_content */ + content_type = build_mime_content(); + + single_fields = mailmime_single_fields_new(mime_fields, content_type); + + /* do the things */ + + mailmime_single_fields_free(single_fields); + mailmime_fields_free(mime_fields); +} + +void display_mime_single_fields(struct mailmime_single_fields * single_fields) +{ + if (single_fields->fld_content != NULL) { + printf("content type:\n"); + display_mime_content(single_fields->fld_content); + printf("\n"); + } + if (single_fields->fld_content_charset != NULL) { + printf("content type charset: %s\n", + single_fields->fld_content_charset); + printf("\n"); + } + if (single_fields->fld_content_boundary != NULL) { + printf("content type boundary: %s\n", + single_fields->fld_content_boundary); + printf("\n"); + } + if (single_fields->content_name != NULL) { + printf("content type name: %s\n", single_fields->content_name); + printf("\n"); + } + if (single_fields->fld_encoding != NULL) { + printf("content transfer encoding:\n"); + display_mime_mechanism(single_fields->fld_encoding); + printf("\n"); + } + if (single_fields->fld_id != NULL) { + printf("content id: %s\n", single_fields->fld_id); + printf("\n"); + } + if (single_fields->fld_description != NULL) { + printf("content description: %s\n", single_fields->fld_description); + printf("\n"); + } + if (single_fields->fld_version != 0) { + printf("mime version: %i.%i\n", + single_fields->fld_version>> 16, + single_fields->fld_version & 0xFFFF); + printf("\n"); + } + if (single_fields->fld_disposition != NULL) { + printf("content disposition:\n"); + display_mime_disposition(single_fields->fld_disposition); + printf("\n"); + } + if (single_fields->fld_disposition_filename != NULL) { + printf("content disposition filename: %s\n", + single_fields->fld_disposition_filename); + printf("\n"); + } + if (single_fields->fld_disposition_creation_date != NULL) { + printf("content disposition creation date: %s\n", + single_fields->fld_disposition_creation_date); + printf("\n"); + } + if (single_fields->fld_disposition_modification_date != NULL) { + printf("content disposition modification date: %s\n", + single_fields->fld_disposition_modification_date); + printf("\n"); + } + if (single_fields->fld_disposition_read_date != NULL) { + printf("content disposition read date: %s\n", + single_fields->fld_disposition_read_date; + printf("\n"); + } + if (single_fields->fld_disposition_size != (size_t) -1) { + printf("content disposition size : %i\n", + single_fields->fld_disposition_size); + printf("\n"); + } + if (single_fields->language != NULL) { + printf("content language:\n"); + display_mime_language(single_fields->fld_language); + printf("\n"); + } +} + + _________________________________________________________________ + +Parser functions + +mailmime_content_parse + +#include <libetpan/libetpan.h> + +int mailmime_content_parse(const char * message, size_t length, + size_t * index, + struct mailmime_content ** result); + + + This function will parse the content of a Content-Type header field. + + * message is a string containing the MIME content type. + * length is the size of the given string. + * index is a pointer to the start of the address in the given + string, (* index) is modified to point at the end of the parsed + data. + * result. The result of the parse operation is stored in (* result) + (see the Section called mailmime_content - MIME content type + (Content-Type)). + + Example 4-16. Parsing MIME content type +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Type") == 0) { + struct mailmime_content * content_type; + size_t current_index; + + current_index = 0; + r = mailmime_content_parse(field->fld_data.fld_optional_field-> +fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &content_type); + if (r == MAILIMF_NO_ERROR) { + display_mime_content(content_type); + /* do the things */ + status = EXIT_SUCCESS; + mailmime_content_free(content_type); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_description_parse + +#include >libetpan/libetpan.h< + +int mailmime_description_parse(const char * message, size_t length, + size_t * index, + char ** result); + + + This will parse the content of Content-Description MIME header field. + + * message is a string containing the MIME content description. + * length is the size of the given string. + * index is a pointer to the start of the address in the given + string, (* index) is modified to point at the end of the parsed + data. + * result. The result of the parse operation is stored in (* result). + The result string must be freed with free(). + + Example 4-17. Parsing MIME description +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Description") == 0) { + char * description; + size_t current_index; + + current_index = 0; + r = mailmime_description_parse(field->fld_data.fld_optional_fie +ld->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &description); + if (r == MAILIMF_NO_ERROR) { + printf("%s\n", description); + /* do the things */ + status = EXIT_SUCCESS; + free(description); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_encoding_parse + +#include >libetpan/libetpan.h< + +int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result); + + + This function will parse the content of Content-Transfer-Encoding + header field. + + * message is a string containing the MIME encoding mechanism. + * length is the size of the given string. + * index is a pointer to the start of the address in the given + string, (* index) is modified to point at the end of the parsed + data. + * result. The result of the parse operation is stored in (* result) + (see the Section called mailmime_mechanism - MIME transfer + encoding mechanism (Content-Transfer-Encoding)). + + Example 4-18. parsing MIME encoding mechanism +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Transfer-Encoding") == 0) { + struct mailmime_content * encoding; + size_t current_index; + + current_index = 0; + r = mailmime_encoding_parse(field->fld_data.fld_optional_field- +>fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &encoding); + if (r == MAILIMF_NO_ERROR) { + display_mime_mechanism(encoding); + /* do the things */ + status = EXIT_SUCCESS; + mailmime_mechanism_free(encoding); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_field_parse + +#include <libetpan/libetpan.h> + +int +mailmime_field_parse(struct mailimf_optional_field * field, + struct mailmime_field ** result); + + + This function will parse a MIME header field. + + * field is a non-parsed field (see the Section called + mailimf_optional_field - non-standard header in Chapter 3). + result. The result of the parse operation is stored in (* result) + (see the Section called mailmime_field - MIME header field). + + Example 4-19. parsing MIME header field +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + r = mailmime_field_parse(field->fld_data.fld_optional_field, + &mime_fields); + if (r == MAILIMF_NO_ERROR) { + display_mime_field(mime_field); + mailmime_field_free(mime_field); + status = EXIT_SUCCESS; + } + } + } + + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_id_parse + +#include >libetpan/libetpan.h< + +int mailmime_id_parse(const char * message, size_t length, + size_t * index, char ** result); + + + This will parse the content of Content-ID MIME header field. + + * message is a string containing the MIME content identifier. + * length is the size of the given string. + * index is a pointer to the start of the address in the given + string, (* index) is modified to point at the end of the parsed + data. + * result. The result of the parse operation is stored in (* result). + The result string must be freed with free(). + + Example 4-20. Parsing MIME content identifier +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-ID") == 0) { + char * id; + size_t current_index; + + current_index = 0; + r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_v +alue, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &id); + if (r == MAILIMF_NO_ERROR) { + printf("%s\n", id); + /* do the things */ + status = EXIT_SUCCESS; + free(id); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_fields_parse + +#include <libetpan/libetpan.h> + +int +mailmime_fields_parse(struct mailimf_fields * fields, + struct mailmime_fields ** result); + + + This function will parse a MIME header fields. + + * fields is a list of RFC 2822 fields (see the Section called + mailimf_fields - list of header fields in Chapter 3). + result. The result of the parse operation is stored in (* result) + (see the Section called mailmime_fields - header fields). + + Example 4-21. parsing MIME header fields +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + struct mailmime_fields * mime_fields; + + r = mailmime_fields_parse(f, &mime_fields); + if (r == MAILIMF_NO_ERROR) { + display_mime_fields(mime_fields); + mailmime_fields_free(mime_fields); + status = EXIT_SUCCESS; + } + + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_version_parse + +#include <libetpan/libetpan.h> + +int mailmime_version_parse(const char * message, size_t length, + size_t * index, + uint32_t * result); + + + This will parse the content of MIME-Version MIME header field. + + * message is a string containing the MIME version. + * length is the size of the given string. + * index is a pointer to the start of the address in the given + string, (* index) is modified to point at the end of the parsed + data. + * result. The result of the parse operation is stored in (* result) + (see the Section called mailmime_field - MIME header field). + + Example 4-22. parsing MIME version +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "MIME-Version") == 0) { + uint32_t version; + size_t current_index; + + current_index = 0; + r = mailmime_version_parse(field->fld_data.fld_optional_field-> +fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &version); + if (r == MAILIMF_NO_ERROR) { + printf("%i.%i\n", version >> 16, version & 0xFFFF); + /* do the things */ + status = EXIT_SUCCESS; + free(description); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_parameter_parse + +#include <libetpan/libetpan.h> + +int mailmime_parameter_parse(const char * message, size_t length, + size_t * index, + struct mailmime_parameter ** result); + + + This will parse a MIME parameter (parameter of Content-Type or + parameter of Content-Disposition). + + * message is a string containing the MIME parameter. + * length is the size of the given string. + * index is a pointer to the start of the address in the given + string, (* index) is modified to point at the end of the parsed + data. + * result. The result of the parse operation is stored in (* result) + (see the Section called mailmime_parameter - MIME type parameter). + + Example 4-23. parsing a MIME parameter +#include <libetpan/libetpan.h> + +#define PARAM_STR "foo=bar" + +int main(int argc, char ** argv) +{ + int fd; + int r; + size_t current_index; + struct mailmime_parameter * param; + int status; + + status = EXIT_FAILURE; + + current_index = 0; + r = mailmime_parameter_parse(PARAM_STR, sizeof(PARAM_STR) - 1, + ¤t_index, ¶m); + if (r == MAILIMF_NO_ERROR) { + display_mime_parameter(param); + /* do the things */ + mailmime_parameter_free(param); + status = EXIT_SUCCESS; + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_language_parse + +#include <libetpan/libetpan.h> + +int mailmime_language_parse(const char * message, size_t length, + size_t * index, + struct mailmime_language ** result); + + + This function will parse the content of a Content-Language header. + + * message is a string containing the MIME content language. + * length is the size of the given string. + * index is a pointer to the start of the address in the given + string, (* index) is modified to point at the end of the parsed + data. + * result. The result of the parse operation is stored in (* result) + (see the Section called mailmime_language - Language of MIME + part). + + Example 4-24. Parsing the MIME content langage +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Language") == 0) { + struct mailmime_language * lang; + size_t current_index; + + current_index = 0; + r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_v +alue, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &lang); + if (r == MAILIMF_NO_ERROR) { + display_mime_language(lang); + /* do the things */ + status = EXIT_SUCCESS; + free(id); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_disposition_parse + +#include <libetpan/libetpan.h> + +int mailmime_disposition_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition ** result); + + + This function will parse the content of a Content-Disposition MIME + header field. + + * message is a string containing the MIME content disposition. + * length is the size of the given string. + * index is a pointer to the start of the address in the given + string, (* index) is modified to point at the end of the parsed + data. + * result. The result of the parse operation is stored in (* result) + (see the Section called mailmime_disposition - MIME disposition + information (Content-Disposition)). + + Example 4-25. Parsing the MIME content disposition +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Disposition") == 0) { + struct mailmime_disposition * dsp; + size_t current_index; + + current_index = 0; + r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_v +alue, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &dsp); + if (r == MAILIMF_NO_ERROR) { + display_mime_disposition(dsp); + /* do the things */ + status = EXIT_SUCCESS; + free(id); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_disposition_type_parse + +#include <libetpan/libetpan.h> + +int +mailmime_disposition_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_type ** + result); + + + This function will parse the type of MIME content disposition. + + * message is a string containing the MIME content disposition type. + * length is the size of the given string. + * index is a pointer to the start of the address in the given + string, (* index) is modified to point at the end of the parsed + data. + * result. The result of the parse operation is stored in (* result) + (see the Section called mailmime_disposition_type - Type of MIME + disposition). + + Example 4-26. parsing a MIME content disposition type +#include <libetpan/libetpan.h> + +#define DSP_TYPE_STR "attachment" + +int main(int argc, char ** argv) +{ + int fd; + int r; + size_t current_index; + struct mailmime_disposition_type * dsp_type; + int status; + + status = EXIT_FAILURE; + + current_index = 0; + r = mailmime_disposition_type_parse(DSP_TYPE_STR, sizeof(DSP_TYPE_STR) - 1, + ¤t_index, &dsp_type); + if (r == MAILIMF_NO_ERROR) { + display_mime_disposition_type(dsp_type); + /* do the things */ + mailmime_disposition_type_free(dsp_type); + status = EXIT_SUCCESS; + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_encoded_phrase_parse + +#include <libetpan/libetpan.h> + +int mailmime_encoded_phrase_parse(const char * default_fromcode, + const char * message, size_t length, + size_t * index, const char * tocode, + char ** result); + + + This function will decode a MIME encoded header string, encoded with + RFC 2047. + + * default_fromcode is the default code to use for parts of string + that are not marked with charset. + * message is the string to decode. + * length is the size of the given string. + * index is a pointer to the start of the address in the given + string, (* index) is modified to point at the end of the parsed + data. + * tocode is the destination charset for decoding. + * result. The result of the parse operation is stored in (* result). + + Example 4-27. decoding a MIME encoded header string +#include <libetpan/libetpan.h> + +#define TEST_STRING "=?iso-8859-1?ab?= =?iso-8859-15?cd?=" + +int main(int argc, char ** argv) +{ + size_t cur_token; + char * decoded_subject; + + cur_token = 0; + mailmime_encoded_phrase_parse("iso-8859-1", + TEST_STRING, sizeof(TEST_STRING), + &cur_token, "iso-8859-1", &decoded_subject); + + printf("%s\n", decoded_subject); + + /* do the things */ + + free(decoded_subject); +} + + _________________________________________________________________ + +mailmime_parse + +#include <libetpan/libetpan.h> + +int mailmime_parse(const char * message, size_t length, + size_t * index, struct mailmime ** result); + + + This will parse a MIME message. + + * message is a string containing the MIME message. + * length is the size of the given string. + * index is a pointer to the start of the address in the given + string, (* index) is modified to point at the end of the parsed + data. + * result. The result of the parse operation is stored in (* result) + (see the Section called mailmime - MIME part). + + Example 4-28. parsing a MIME message +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailmime * mime; + size_t current_index; + + current_index = 0; + r = mailmime_parse(mem, stat_info.st_size, + ¤t_index, &mime); + if (r == MAILIMF_NO_ERROR) { + display_mime(mime); + /* do the things */ + status = EXIT_SUCCESS; + mailmime_free(mime); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_base64_body_parse + +#include <libetpan/libetpan.h> + +int mailmime_base64_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + + + This function will parse a body part encoded using base64. + + * message is a string encoded using base64. + * length is the size of the given string. + * index is a pointer to the start of the address in the given + string, (* index) is modified to point at the end of the parsed + data. + * result. The result of the parse operation is stored in (* result) + The result must be freed with mmap_string_unref(). + + Example 4-29. Parsing a base64 encoded part +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_base64_body_parse(mem, stat_info.st_size, + ¤t_index, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_quoted_printable_body_parse + +#include <libetpan/libetpan.h> + +int mailmime_quoted_printable_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len, int in_header); + + + This function will parse a body part encoded using quoted printable. + + * message is a string encoded using quoted printable. + * length is the size of the given string. + * index is a pointer to the start of the address in the given + string, (* index) is modified to point at the end of the parsed + data. + * result. The result of the parse operation is stored in (* result) + The result must be freed with mmap_string_unref(). + + Example 4-30. Parsing a quoted printable encoded part +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_quoted_printable_body_parse(mem, stat_info.st_size, + ¤t_index, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_binary_body_parse + +#include <libetpan/libetpan.h> + +int mailmime_binary_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + + + This function will parse a body part encoded using binary (no + encoding). + + * message is a string encoded using binary. + * length is the size of the given string. + * index is a pointer to the start of the address in the given + string, (* index) is modified to point at the end of the parsed + data. + * result. The result of the parse operation is stored in (* result) + The result must be freed with mmap_string_unref(). + + Example 4-31. Parsing a binary encoded part +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_binary_body_parse(mem, stat_info.st_size, + ¤t_index, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_part_parse + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +int mailmime_part_parse(const char * message, size_t length, + size_t * index, + int encoding, char ** result, size_t * result_len); + + + This function will parse a body part encoded using a given MIME + encoding mechanism. + + * message is a string encoded using binary. + * length is the size of the given string. + * index is a pointer to the start of the address in the given + string, (* index) is modified to point at the end of the parsed + data. + * encoding is a MIME encoding mechanism. The value can be + MAILMIME_MECHANISM_7BIT, MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64 or MAILMIME_MECHANISM_TOKEN (see the + Section called mailmime_mechanism - MIME transfer encoding + mechanism (Content-Transfer-Encoding)). + * result. The result of the parse operation is stored in (* result) + The result must be freed with mmap_string_unref(). + + Example 4-32. Parsing a MIME encoded part +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_part_parse(mem, stat_info.st_size, ¤t_index, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +Rendering of MIME parts + +mailmime_fields_write, mailmime_content_write and +mailmime_content_type_write + +#include <libetpan/libetpan.h> + +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields); + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content); + + + mailmime_fields_write render the MIME header fields. + + mailmime_content_write render the MIME content type header field. + + mailmime_content_write render the content of the MIME content type + header field. + + * col current column is given for wrapping purpose in (* col), the + resulting columns will be returned.. + * f is the file descriptor. It can be stdout for example. + * fields is the header fields (see the Section called + mailmime_fields - header fields). + * content is the header fields (see the Section called + mailmime_content - MIME content type (Content-Type)). + + Example 4-33. rendering MIME header fields +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_mime * mime_fields; + int col; + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + col = 0; + mailmime_fields_write(stdout, &col, mime_fields); + + mailmime_fields_free(mime_fields); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + int col; + + /* look at the example in mailmime_content to see how to + build a mailmime_fields */ + content = build_mime_content(); + + col = 0; + mailmime_content_write(stdout, &col, mime_fields); + + mailmime_content_free(content); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + int col; + + /* look at the example in mailmime_content to see how to + build a mailmime_fields */ + content = build_mime_content(); + + col = 0; + mailmime_content_type_write(stdout, &col, mime_fields); + + mailmime_content_free(content); +} + + _________________________________________________________________ + +mailmime_write + +#include <libetpan/libetpan.h> + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info); + + + This function will render a MIME message. + + * col current column is given for wrapping purpose in (* col), the + resulting columns will be returned.. + * f is the file descriptor. It can be stdout for example. + * build_info is the MIME message to render. + _________________________________________________________________ + +mailmime_quoted_printable_write and mailmime_base64_write + +#include <libetpan/libetpan.h> + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size); + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size); + + + mailmime_quoted_printable_write() will render a string to quoted + printable. + + mailmime_base64_write() will render a string to base64. + + * col current column is given for wrapping purpose in (* col), the + resulting columns will be returned.. + * f is the file descriptor. It can be stdout for example. + * text is the string to render. + * size is the size of the string to render. + + Example 4-34. render base64 or quoted printable +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + int col; + + col = 0; + mailmime_quoted_printable_write(stdout, &col, + "this is a test", 14); +} + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + int col; + + col = 0; + mailmime_base64_write(stdout, &col, "this is a test", 14); +} + + _________________________________________________________________ + +mailmime_data_write + +#include <libetpan/libetpan.h> + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext); + + + mailmime_data_write will render MIME data. + + * col current column is given for wrapping purpose in (* col), the + resulting columns will be returned.. + * f is the file descriptor. It can be stdout for example. + * data is the data to render (see the Section called mailmime_data - + Content of MIME part). + _________________________________________________________________ + +Creation functions + +mailmime_disposition_new_filename and mailmime_disposition_new_with_data + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition * +mailmime_disposition_new_filename(int type, char * filename); + +struct mailmime_disposition * +mailmime_disposition_new_with_data(int type, + char * filename, char * creation_date, char * modification_date, + char * read_date, size_t size); + + + These functions will create a MIME content disposition information. + + * type a standard MIME disposition : + MAILMIME_DISPOSITION_TYPE_INLINE or + MAILMIME_DISPOSITION_TYPE_ATTACHMENT. + filename is the filename. + creation_date is the creation date. + modification_date is the modification date. + read_date is the last read date. + size is the size of the file. + * This will return a MIME content disposition (see the Section + called mailmime_disposition - MIME disposition information + (Content-Disposition)). + + Example 4-35. creating a MIME content disposition + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_disposition * disposition; + + disposition = + mailmime_disposition_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + strdup("foo-bar.txt")); + + /* do the things */ + + mailmime_disposition_free(disposition); +} + + _________________________________________________________________ + +mailmime_fields_new_empty and mailmime_fields_add + +#include <libetpan/libetpan.h> + +struct mailmime_fields * mailmime_fields_new_empty(void); + +int mailmime_fields_add(struct mailmime_fields * fields, + struct mailmime_field * field); + + + mailmime_fields_new_empty() will create a new empty MIME header fields + list. + + mailmime_fields_add() will add MIME header fields to the MIME header + fields list. + + * fields. The MIME header field will be added to this MIME header + fields list (see the Section called mailmime_fields - header + fields). + * field is the MIME header field to add (see the Section called + mailmime_field - MIME header field). + + Example 4-36. creating a MIME header fields list +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_fields * fields; + struct mailmime_field * field; + + fields = mailmime_fields_new_empty(); + field = build_mime_field(); + + /* do the things */ + + mailmime_fields_add(fields, field); + + mailmime_fields_free(fields); +} + + _________________________________________________________________ + +mailmime_fields_new_with_data and mailmime_fields_new_with_version + +#include <libetpan/libetpan.h> + +struct mailmime_fields * +mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +struct mailmime_fields * +mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + + + mailmime_fields_new_with_data() will create a MIME header fields list + with all the given fields (NULL can be used for the value if the field + must not be present). MIME-Version header field will not be added. + + mailmime_fields_new_with_version() will create a MIME header fields + list with all the given fields (NULL can be used for the value if the + field must not be present). MIME-Version header field will be added. + + Example 4-37. creating new fields +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_disposition * disposition; + struct mailmime_fields * mime_fields; + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL); + + disposition = + mailmime_disposition_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + strdup("foo-bar.txt")); + + mime_fields = mailmime_fields_new_with_version(encoding, NULL, + NULL, disposition, NULL); + + /* do the things */ + + mailmime_fields_free(mime_fields); +} + + _________________________________________________________________ + +mailmime_get_content_message + +#include <libetpan/libetpan.h> + +struct mailmime_content * mailmime_get_content_message(void); + +struct mailmime_content * mailmime_get_content_text(void); + +struct mailmime_content * mailmime_content_new_with_str(const char * str); + + + mailmime_get_content_message() will create a MIME content type + message/rfc822. + + mailmime_get_content_text() will create a MIME content type + plain/text. + + mailmime_get_content_new_with_str() will create a MIME content type + given by the string plain/text. + + str. This string will NOT be referenced by any structure. This string + will only be parsed to create the structure. + + Example 4-38. Creating a MIME content type +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + + content = mailmime_get_content_message(); + + /* do the things */ + + mailmime_content_free(content); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + /* do the things */ + + mailmime_content_free(content); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + + content = mailmime_get_content_new_with_str("multipart/mixed"); + + /* do the things */ + + mailmime_content_free(content); +} + + _________________________________________________________________ + +mailmime_data_new_data and mailmime_data_new_file + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_data * +mailmime_data_new_data(int encoding, int encoded, + const char * data, size_t length); + +struct mailmime_data * +mailmime_data_new_file(int encoding, int encoded, + char * filename); + + + mailmime_data_new_data() will create a new MIME content, using a + string in memory. + + mailmime_data_new_file() will create a new MIME content, using a file. + + * encoding is the MIME encoding mechanism used to encode this part. + The value can be MAILMIME_MECHANISM_7BIT, MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, MAILMIME_MECHANISM_QUOTED_PRINTABLE or + MAILMIME_MECHANISM_BASE64 (see the Section called + mailmime_mechanism - MIME transfer encoding mechanism + (Content-Transfer-Encoding)). + * encoded is set to 1 if the part is already encoded with the + mechanism given in encoding. + * data is a pointer to the content of the part. + * length is the length of the data. + * filename is the name of the file. + + Example 4-39. creating MIME content +#include <libetpan/libetpan.h> + +#define DATA_STR "my data" + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new_data(MAILMIME_MECHANISM_BASE64, 0, + DATA_STR, sizeof(DATA_STR) - 1); + + /* do the things */ + + mailmime_data_free(data); +} + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new_file(MAILMIME_MECHANISM_BASE64, 0, + strdup("foo-bar.txt")); + + /* do the things */ + + mailmime_data_free(data); +} + + _________________________________________________________________ + +mailmime_new_message_data, mailmime_new_empty and mailmime_new_with_content + +#include <libetpan/libetpan.h> + +struct mailmime * +mailmime_new_message_data(struct mailmime * msg_mime); + +struct mailmime * +mailmime_new_empty(struct mailmime_content * content, + struct mailmime_fields * mime_fields); + +int +mailmime_new_with_content(const char * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result); + +struct mailmime * mailmime_multiple_new(const char * type); + + + mailmime_new_message_data() will create a new MIME message with the + given subpart. + + mailmime_new_empty() will create a new MIME part with the given + content type and MIME fields but with no content. + + mailmime_new_with_content() will create a new MIME part with a content + type given by a string and a given MIME fields list. + + mailmime_multiple_new() will create a new MIME multipart with a + content type given by a string. + + * msg_mime is the sub part to add to the MIME message when creating + it (see the Section called mailmime - MIME part). + * content is the content type of the part to create (see the Section + called mailmime_content - MIME content type (Content-Type)). + * content_type is the content type of the part to create given by a + string. + * mime_fields is the list of MIME header fields (see the Section + called mailmime_fields - header fields). + + Example 4-40. creating a MIME part +#include <libetpan/libetpan.h> + +#define DATA_STR "my data" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailmime * single_part; + + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + mailmime_new_with_content("plain/text", mime_fields, &single_part); + + mailmime_set_body_text(single_part, DATA_STR, sizeof(DATA_STR) - 1); + + mime = mailmime_new_message_data(single_part); + + /* do the things */ + + mailmime_free(mime); +} + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailmime * single_part; + struct mailmime_content * content; + + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + content = mailmime_get_content_text(); + single_part = mailmime_new_empty(content, mime_fields); + + mailmime_set_body_text(single_part, DATA_STR, sizeof(DATA_STR) - 1); + + mime = mailmime_new_message_data(single_part); + + /* do the things */ + + mailmime_free(mime); +} + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + + mime = mailmime_multiple_new("multipart/mixed"); + + /* do the things */ + + mailmime_free(mime); +} + + _________________________________________________________________ + +mailmime_set_preamble_file, mailmime_set_epilogue_file, +mailmime_set_preamble_text and mailmime_set_epilogue_text + +#include <libetpan/libetpan.h> + +int mailmime_set_preamble_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_epilogue_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_preamble_text(struct mailmime * build_info, + char * data_str, size_t length); + +int mailmime_set_epilogue_text(struct mailmime * build_info, + char * data_str, size_t length); + + + mailmime_set_preamble_file() will define the preamble of a multipart. + + mailmime_set_preamble_text() will define the preamble of a multipart. + + mailmime_set_epilogue_file() will define the epilogue of a multipart. + + mailmime_set_preamble_text() will define the preamble of a multipart. + + * build_info is the MIME part to modify (see the Section called + mailmime - MIME part). + * data_str is the string to define as epilogue or prologue. + * length is the length of the string to define as epilogue or + prologue. + * filename is the name of the file which content will be defined as + epilogue or prologue. + + Example 4-41. setting preamble and epilogue +#include <libetpan/libetpan.h> + +#define DATA_STR "test foo bar" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + + mime = mailmime_multiple_new("multipart/mixed"); + + mailmime_set_preamble_file(mime, strdup("foo-bar.txt")); + + mailmime_set_epilogue_data(mime, DATA_STR, sizeof(DATA_STR) - 1); + + /* do the things */ + + mailmime_free(mime); +} + + _________________________________________________________________ + +mailmime_set_body_file and mailmime_set_body_text + +#include <libetpan/libetpan.h> + +int mailmime_set_body_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_body_text(struct mailmime * build_info, + char * data_str, size_t length); + + + mailmime_set_body_file() will define the body of a single part. + + mailmime_set_body_text() will define the body of a single part. + + * build_info is the MIME part to modify (see the Section called + mailmime - MIME part). + * data_str is the string to define as the body of the part. + * length is the length of the string to define as the body of the + part. + * filename is the name of the file which content will be defined as + the body of the part. + + Example 4-42. creating a MIME part +#include <libetpan/libetpan.h> + +#define DATA_STR "my data" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + mailmime_new_with_content("plain/text", mime_fields, &mime); + + mailmime_set_body_text(mime, DATA_STR, sizeof(DATA_STR) - 1); + + + + /* do the things */ + + mailmime_free(mime); +} + + _________________________________________________________________ + +mailmime_add_part, mailmime_remove_part, mailmime_smart_add_part and +mailmime_smart_remove_part + +#include <libetpan/libetpan.h> + +int mailmime_add_part(struct mailmime * build_info, + struct mailmime * part); + +void mailmime_remove_part(struct mailmime * mime); + +int mailmime_smart_add_part(struct mailmime * mime, + struct mailmime * mime_sub); + +int mailmime_smart_remove_part(struct mailmime * mime); + + + mailmime_add_part() will add a sub MIME part. + + mailmime_remove_part() will detach the given sub part from its parent. + + mailmime_smart_add_part() will add a sub MIME part. If the parent part + is a message and no child exist, the part is set as the child. If the + parent part is a message and a child already exists, if the child is + multipart, the part to add is added as child of this multipart, else a + multipart is added and the part is added as child of the multipart. + + mailmime_smart_remove_part() will detach the given sub part from its + parent. The sub part will be freed. + + * build_info is the parent MIME part (see the Section called + mailmime - MIME part). + * part is the part to add (see the Section called mailmime - MIME + part). + * mime is the parent MIME part (see the Section called mailmime - + MIME part). + * mime_sub is the part to add or to detach (see the Section called + mailmime - MIME part). + + Example 4-43. modifying MIME structure +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_add_part(mime, sub_mime); + + /* do the things */ + + mailmime_free(mime); + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime * other_sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + sub_mime = mailmime_new_empty(content, mime_fields); + + content = mailmime_get_content_text(); + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + other_sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_smart_add_part(mime, sub_mime); + mailmime_smart_add_part(mime, other_sub_mime); + + /* do the things */ + + mailmime_free(mime); + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_add_part(mime, sub_mime); + + mailmime_remove_part(sub_mime); + + /* do the things */ + + mailmime_free(sub_mime); + mailmime_free(mime); + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_add_part(mime, sub_mime); + + mailmime_smart_remove_part(sub_mime); + + /* do the things */ + + mailmime_free(mime); +} + + _________________________________________________________________ + +mailmime_set_imf_fields + +#include <libetpan/libetpan.h> + +void mailmime_set_imf_fields(struct mailmime * build_info, + struct mailimf_fields * fields); + + + mailmime_set_imf_fields() will set the fields of the given MIME + message. + + * build_info is the MIME message to modify (see the Section called + mailmime - MIME part). + * fields is the header fields to set for the message (see the + Section called mailimf_fields - list of header fields in Chapter + 3). + + Example 4-44. modifying MIME structure +#include <libetpan/libetpan.h> + +#define DATA_STR "test foo bar" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailmime_fields * mime_fields; + struct mailimf_fields * imf_fields; + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT); + + mailmime_new_with_content("text/plain", mime_fields, &mime); + + mailmime_set_body_text(mime, DATA_STR, sizeof(DATA_STR) - 1); + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + imf_fields = build_fields(); + + mailmime_set_imf_fields(mime, imf_fields); + + /* do the things */ + + mailmime_free(mime); +} + + _________________________________________________________________ + +mailmime_fields_new_encoding and mailmime_fields_new_filename + +#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_fields * mailmime_fields_new_encoding(int encoding_type); + +struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, + char * filename, int encoding_type); + + + mailmime_fields_new_encoding() will create a list of MIME header + fields with only Content-Transfer-Encoding. + + mailmime_fields_new_filename() will create a list of MIME header + fields with Content-Transfer-Encoding and Content-Disposition. + + The result will be a list of MIME header fields (see the Section + called mailmime_fields - header fields). + + * encoding_type is the MIME encoding mechanism. The value can be + MAILMIME_MECHANISM_7BIT, MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, MAILMIME_MECHANISM_QUOTED_PRINTABLE or + MAILMIME_MECHANISM_BASE64 (see the Section called + mailmime_mechanism - MIME transfer encoding mechanism + (Content-Transfer-Encoding)). + * dsp_type is the disposition type. The value can be + MAILMIME_DISPOSITION_TYPE_INLINE or + MAILMIME_DISPOSITION_TYPE_ATTACHMENT (see the Section called + mailmime_disposition_type - Type of MIME disposition). + * filename is the filename for MIME content disposition. + + Example 4-45. creating MIME fields with only Content-Transfer-Encoding +#include <libetpan/libetpan.h> + +int main(void) +{ + struct mailmime_fields * fields; + + fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + /* do the things */ + + mailmime_fields_free(fields); +} + +int main(void) +{ + struct mailmime_fields * fields; + + fields = + mailmime_fields_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + strdup("foo-bar.txt"), MAILMIME_MECHANISM_BASE64); + + /* do the things */ + + mailmime_fields_free(fields); +} + + _________________________________________________________________ + +Helper functions + +mailmime_transfer_encoding_get + +#include <libetpan/libetpan.h> + +int mailmime_transfer_encoding_get(struct mailmime_fields * fields); + + + mailmime_transfer_encoding_get() will return the standard MIME + encoding mechanism. + + * fields is the list of MIME header fields. + * An integer representing the MIME encoding mechanism will be + returned (see the Section called mailmime_mechanism - MIME + transfer encoding mechanism (Content-Transfer-Encoding)). + + Example 4-46. extracting MIME encoding mechanism +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + struct mailmime_fields * mime_fields; + + r = mailmime_fields_parse(f, &mime_fields); + if (r == MAILIMF_NO_ERROR) { + int encoding; + + encoding = mailmime_transfer_encoding_get(mime_fields); + + /* do the things */ + + mailmime_fields_free(mime_fields); + status = EXIT_SUCCESS; + } + + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +mailmime_content_charset_get and mailmime_content_param_get + +#include <libetpan/libetpan.h> + +char * mailmime_content_charset_get(struct mailmime_content * content); + +char * mailmime_content_param_get(struct mailmime_content * content, + char * name); + +char * mailmime_extract_boundary(struct mailmime_content * content_type); + + + mailmime_content_charset_get() will return the charset parameter of + MIME content type. + + mailmime_content_param_get() will return the value of a given + parameter of MIME content type. + + mailmime_extract_boundary() will return the charset parameter of MIME + content type. + + * content is the MIME content type. + * name is the name of the parameter to extract. + * With mailmime_extract_boundary(), the returned value must be freed + with free(). + + Example 4-47. extracting information from MIME content type +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Type") == 0) { + struct mailmime_content * content_type; + size_t current_index; + + current_index = 0; + r = mailmime_content_parse(field->fld_data.fld_optional_field-> +fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &content_type); + if (r == MAILIMF_NO_ERROR) { + char * charset; + char * name; + char * boundary; + + charset = mailmime_content_charset_get(content_type); + name = mailmime_content_param_get(content_type, "name"); + boundary = mailmime_extract_boundary(content_type); + + /* do the things */ + + free(boundary); + + status = EXIT_SUCCESS; + mailmime_content_free(content_type); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + + _________________________________________________________________ + +Chapter 5. Storages, folders, messages + +Introduction + + This part will give the definition of some objects. + _________________________________________________________________ + +Message + + A message is the common e-mail message or news message you read or + send. + _________________________________________________________________ + +MIME part + + A message can have attachment such as images or other documents. The + attachment are organized into a tree structure. Each node of this + structure is a MIME part. + _________________________________________________________________ + +Mailbox + + A mailbox will contain a given number of messages. + _________________________________________________________________ + +Storage + + A storage is a "physical" localisation of your mailbox. This can be on + a filesystem (local or remote disk, this is the case of MH, mbox and + maildir), or this can be on a remote host (this is the case for POP3, + IMAP or NNTP). + _________________________________________________________________ + +Folder + + A storage, for the same user, can contain a given number of mailboxes, + depending the storage capabilities, then, the storage driver + capabilities. With etPan!, MH, IMAP and NNTP storages can have more + than one mailbox. The mailboxes will be called folders. On storage + where we only have one mailbox, the unique mailbox is the unique + folder. + _________________________________________________________________ + +Session + + The session is the network connection or the entity to which the + commands of the drivers are given. + _________________________________________________________________ + +Error codes + + Error codes returned as integers can be one of the following : +enum { + MAIL_NO_ERROR = 0, + MAIL_NO_ERROR_AUTHENTICATED, + MAIL_NO_ERROR_NON_AUTHENTICATED, + MAIL_ERROR_NOT_IMPLEMENTED, + MAIL_ERROR_UNKNOWN, + MAIL_ERROR_CONNECT, + MAIL_ERROR_BAD_STATE, + MAIL_ERROR_FILE, + MAIL_ERROR_STREAM, + MAIL_ERROR_LOGIN, + MAIL_ERROR_CREATE, /* 10 */ + MAIL_ERROR_DELETE, + MAIL_ERROR_LOGOUT, + MAIL_ERROR_NOOP, + MAIL_ERROR_RENAME, + MAIL_ERROR_CHECK, + MAIL_ERROR_EXAMINE, + MAIL_ERROR_SELECT, + MAIL_ERROR_MEMORY, + MAIL_ERROR_STATUS, + MAIL_ERROR_SUBSCRIBE, /* 20 */ + MAIL_ERROR_UNSUBSCRIBE, + MAIL_ERROR_LIST, + MAIL_ERROR_LSUB, + MAIL_ERROR_APPEND, + MAIL_ERROR_COPY, + MAIL_ERROR_FETCH, + MAIL_ERROR_STORE, + MAIL_ERROR_SEARCH, + MAIL_ERROR_DISKSPACE, + MAIL_ERROR_MSG_NOT_FOUND, /* 30 */ + MAIL_ERROR_PARSE, + MAIL_ERROR_INVAL, + MAIL_ERROR_PART_NOT_FOUND, + MAIL_ERROR_REMOVE, + MAIL_ERROR_FOLDER_NOT_FOUND, + MAIL_ERROR_MOVE, + MAIL_ERROR_STARTTLS, + MAIL_ERROR_CACHE_MISS, + MAIL_ERROR_NO_TLS, + MAIL_ERROR_EXPUNGE, + /* misc errors */ + MAIL_ERROR_MISC, + MAIL_ERROR_PROTOCOL, + MAIL_ERROR_CAPABILITY, + MAIL_ERROR_CLOSE, + MAIL_ERROR_FATAL, + MAIL_ERROR_READONLY, + MAIL_ERROR_NO_APOP, + MAIL_ERROR_COMMAND_NOT_SUPPORTED, + MAIL_ERROR_NO_PERMISSION, + MAIL_ERROR_PROGRAM_ERROR, + MAIL_ERROR_SUBJECT_NOT_FOUND, + MAIL_ERROR_CHAR_ENCODING_FAILED, + MAIL_ERROR_SEND, + MAIL_ERROR_COMMAND, +}; + + _________________________________________________________________ + +Storage + +Storage driver + +#include <libetpan/libetpan.h> + +typedef struct mailstorage_driver mailstorage_driver; + +struct mailstorage_driver { + char * sto_name; + int (* sto_connect)(struct mailstorage * storage); + int (* sto_get_folder_session)(struct mailstorage * storage, + char * pathname, mailsession ** result); + void (* sto_uninitialize)(struct mailstorage * storage); +}; + + + This is the driver for a storage. + + * sto_name is the name of the driver. + * sto_connect() connects the storage to the remote access or to the + path in the local filesystem. + * sto_get_folder_session() can have two kinds of behaviour. Either + it creates a new session and independant from the session used by + the storage and select the given mailbox or it selects the given + mailbox in the current session. It depends on the efficiency of + the mail access. + XXX - in the future, this will be moved to the folder driver + * sto_uninitialize() frees the data created with mailstorage + constructor. + _________________________________________________________________ + +Storage + +#include <libetpan/libetpan.h> + +struct mailstorage { + char * sto_id; + void * sto_data; + mailsession * sto_session; + mailstorage_driver * sto_driver; + clist * sto_shared_folders; /* list of (struct mailfolder *) */ + + void * sto_user_data; +}; + + + * sto_id is an identifier for the storage. This can be NULL. + * sto_data is the internal data of the storage. This can only be + changed by the driver. + * sto_session is the session used by the storage. The session can be + used to send commands. + * sto_driver is the driver of the storage. + * sto_shared_folders is the list of folders that share the session + with the storage. This is used internally. + * sto_user_data is a field for free use. The user can store any data + in that field. + _________________________________________________________________ + +mailstorage_new and mailstorage_free + +#include <libetpan/libetpan.h> + +struct mailstorage * mailstorage_new(char * sto_id); + +void mailstorage_free(struct mailstorage * storage); + + + mailstorage_new() initializes a storage structure with an identifier + (sto_id) and with no driver. + + mailstorage_free() free the memory used by a storage. + _________________________________________________________________ + +mailstorage_connect and mailstorage_disconnect + +#include <libetpan/libetpan.h> + +int mailstorage_connect(struct mailstorage * storage); + +void mailstorage_disconnect(struct mailstorage * storage); + + + mailstorage_connect() connects the storage. This function can also be + used to confirm that a storage connection is valid when the storage is + already connected. + + mailstorage_disconnect() disconnects the storage. + _________________________________________________________________ + +IMAP storage + +int imap_mailstorage_init(struct mailstorage * storage, + char * imap_servername, uint16_t imap_port, + char * imap_command, + int imap_connection_type, int imap_auth_type, + char * imap_login, char * imap_password, + int imap_cached, char * imap_cache_directory); + + _________________________________________________________________ + +Example + + Example 5-1. use of storage +int main(void) +{ + struct mailstorage * storage; + int r; + + storage = mailstorage_new(NULL); + + imap_mailstorage_init(storage, "imap.my-servers.org", 0, + NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN, + "my-login", "my-password", 1, "/home/login/.libetpan/cache"); + + r = mailstorage_connect(storage); + if (r == MAIL_NO_ERROR) { + mailstorage_disconnect(storage); + } + + mailstorage_free(storage); +} + + _________________________________________________________________ + +Folder + +Folder driver + +#include <libetpan/libetpan.h> + +typedef struct mailfolder_driver mailfolder_driver; + +struct mailfolder_driver { + int (* fld_get_session)(struct mailfolder * folder, + mailsession ** result); + + int (* fld_noop)(struct mailfolder * folder); + + int (* fld_check)(struct mailfolder * folder); + + int (* fld_expunge)(struct mailfolder * folder); + + int (* fld_status)(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + + int (* fld_append_message)(struct mailfolder * folder, + char * message, size_t size); + + int (* fld_get_messages_list)(struct mailfolder * folder, + struct mailmessage_list ** result); + + int (* fld_get_envelopes_list)(struct mailfolder * folder, + struct mailmessage_list * result); + + int (* fld_get_message)(struct mailfolder * folder, + uint32_t num, mailmessage ** result); + + int (* fld_get_message_by_uid)(struct mailfolder * folder, + const char * uid, mailmessage ** result); +} + + + XXX - this will be implemented in the future. + + * fld_get_session() will return the session this folder should use. + * For other method, you should see the Section called Session + driver. + _________________________________________________________________ + +Folder + +#include <libetpan/libetpan.h> + +struct mailfolder { + char * fld_pathname; + char * fld_virtual_name; + + struct mailstorage * fld_storage; + + mailsession * fld_session; + int fld_shared_session; + clistiter * fld_pos; + + struct mailfolder * fld_parent; + unsigned int fld_sibling_index; + carray * fld_children; /* array of (struct mailfolder *) */ + + void * fld_user_data; +}; + + + * fld_pathname is the pathname specific to the driver. + * fld_virtual_name is the identifier of this folder. This can be + NULL. + * fld_storage is the storage used for this folder (see the Section + called Storage). + * fld_session is the session used for this folder. + * fld_shared_session is set to 1 if the folder use the same session + as the storage. This is used internally. + * fld_pos is the position in the list of folders of the storage. + This is used internally. + * use of fld_parent, fld_sibling_index and fld_children is + deprecated. + * fld_user_data is a field for free use. The user can store any data + in that field. + _________________________________________________________________ + +mailfolder_new and mail_folder_free + +#include <libetpan/libetpan.h> + +struct mailfolder * mailfolder_new(struct mailstorage * fld_storage, + char * fld_pathname, char * fld_virtual_name); + +void mailfolder_free(struct mailfolder * folder); + + + mailfolder_new() initializes a folder structure with an identifier + (fld_virtual_name) with path name (fld_pathname). The folder will be + owned by the given storage (fld_storage). + + mailfolder_free() free the memory used by the folder. + _________________________________________________________________ + +mailfolder_connect and mailfolder_disconnect + +#include <libetpan/libetpan.h> + +int mailfolder_connect(struct mailfolder * folder); + +void mailfolder_disconnect(struct mailfolder * folder); + + + mailfolder_connect() connects the folder. This function can also be + used to confirm that a folder connection is valid when the folder is + already connected. When doing operations with several folders, you + have to be sure that this function has been called before making calls + on folder. + + mailfolder_disconnect() disconnects the folder. + _________________________________________________________________ + +mailfolder_noop + +#include <libetpan/libetpan.h> + +int mailfolder_noop(struct mailfolder * folder); + + + This function will only send noop to the mail access. + _________________________________________________________________ + +mailfolder_check + +#include <libetpan/libetpan.h> + +int mailfolder_check(struct mailfolder * folder); + + + A call to this function will save to disk the internal state of the + selected mailbox (such as flags). + _________________________________________________________________ + +mailfolder_expunge + +#include <libetpan/libetpan.h> + +int mailfolder_expunge(struct mailfolder * folder); + + + A call to this function will delete all messages marked for deletion. + _________________________________________________________________ + +mailfolder_status + +int mailfolder_status(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + + + A call to this function will return some counts of messages in the + mailbox. + _________________________________________________________________ + +mailfolder_append_message + +int mailfolder_append_message(struct mailfolder * folder, + char * message, size_t size); + + + This function will store a new message in the given folder. The + message is given by a string in memory (message) and a size (size). + _________________________________________________________________ + +mailfolder_get_messages_list + +int mailfolder_get_messages_list(struct mailfolder * folder, + struct mailmessage_list ** result); + + + This function will return the list of messages in the given folder + (see the Section called Message list). + _________________________________________________________________ + +mailfolder_get_envelopes_list + +int mailfolder_get_envelopes_list(struct mailfolder * folder, + struct mailmessage_list * result); + + + This function will fill the list of parsed header fields structure in + the mailmessage structures of the given list of messages (result). + _________________________________________________________________ + +mailfolder_get_message + +int mailfolder_get_message(struct mailfolder * folder, + uint32_t num, mailmessage ** result); + + + This function will return the message identified by a message index + (num) This will return a mailmessage structure in (* result) (see the + Section called Message). + _________________________________________________________________ + +mailfolder_get_message_by_uid + +int mailfolder_get_message_by_uid(struct mailfolder * folder, + const char * uid, mailmessage ** result); + + + This function will return the message identified by a unique + identifier (uid) This will return a mailmessage structure in (* + result) (see the Section called Message). + _________________________________________________________________ + +Example + + Example 5-2. use of folder +int main(void) +{ + struct mailstorage * storage; + int r; + + storage = mailstorage_new(NULL); + + imap_mailstorage_init(storage, "imap.my-servers.org", 0, + NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN, + "my-login", "my-password", 1, "/home/login/.libetpan/cache"); + + r = mailstorage_connect(storage); + if (r == MAIL_NO_ERROR) { + struct mailfolder * folder; + + folder = mailfolder_new(storage, "INBOX", NULL); + + r = mailfolder_connect(folder); + if (r == MAIL_NO_ERROR) { + struct mailmessage_list * msg_list; + + mailfolder_get_messages_list(folder, &msg_list); + + /* do the things */ + + mailmessage_list_free(msg_list); + + mailfolder_disconnect(folder); + } + + mailstorage_disconnect(storage); + } + + mailstorage_free(storage); +} + + _________________________________________________________________ + +Message + +Message driver + +#include <libetpan/libetpan.h> + +struct mailmessage_driver { + char * msg_name; + + int (* msg_initialize)(mailmessage * msg_info); + + void (* msg_uninitialize)(mailmessage * msg_info); + + void (* msg_flush)(mailmessage * msg_info); + + void (* msg_check)(mailmessage * msg_info); + + void (* msg_fetch_result_free)(mailmessage * msg_info, + char * msg); + + int (* msg_fetch)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_header)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_body)(mailmessage * msg_info, + char ** result, size_t * result_len); + + int (* msg_fetch_size)(mailmessage * msg_info, + size_t * result); + + int (* msg_get_bodystructure)(mailmessage * msg_info, + struct mailmime ** result); + + int (* msg_fetch_section)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + + int (* msg_fetch_section_header)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_mime)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_body)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_envelope)(mailmessage * msg_info, + struct mailimf_fields ** result); + + int (* msg_get_flags)(mailmessage * msg_info, + struct mail_flags ** result); +}; + + + * msg_name is the name of the driver. + * msg_initialize() will initialize the internal message state (field + msg_data of mailmessage structure (see the Section called + Message). + * msg_uninitialize() will free the internal message state. + * msg_flush() will release memory used by the MIME structure of the + message. + * msg_check() will store the flags of the message into the session, + so that the message can be released without the flags are lost. + * msg_fetch_result_free() will free a string returned by any + fetch_XXX() function. + * msg_fetch() will fetch a message. + * msg_fetch_header() will fetch the header fields of a message. + * msg_fetch_body() will fetch a message without its main header. + * msg_fetch_size() will return the size of a message. + * msg_get_bodystructure will retrieve the MIME structure of the + message. The returned structure must NOT be freed. + * msg_fetch_section() will fetch the content of the section of the + message. + * msg_fetch_section_header() will fetch the header of a section of + the message if the content of the section is a message. + * msg_fetch_section_mime() will fetch the MIME header of a section + of the message. + * msg_fetch_section_body() will fetch the body of a section (without + the headers) of the message if the content of the section is a + message. + * msg_fetch_envelope() will return a given number of parsed header + fields. + * msg_get_flags() will return the flags of the message. The returned + structure must NOT be freed. + _________________________________________________________________ + +Message + +#include <libetpan/libetpan.h> + +struct mailmessage { + mailsession * msg_session; + mailmessage_driver * msg_driver; + uint32_t msg_index; + char * msg_uid; + + size_t msg_size; + struct mailimf_fields * msg_fields; + struct mail_flags * msg_flags; + + int msg_resolved; + struct mailimf_single_fields msg_single_fields; + struct mailmime * msg_mime; + + /* internal data */ + + int msg_cached; + void * msg_data; + + /* + msg_folder field : + used to reference the mailfolder, this is a workaround due + to the problem with initial conception, where folder notion + did not exist. + */ + void * msg_folder; + /* user data */ + void * msg_user_data; +}; + + + * msg_session is the session related to the message (see the Section + called Session). + * msg_driver is the driver used for the message (see the Section + called Message driver). + * msg_index is an index to indentify the message. + * msg_uid is the unique identifier of the message, valid accross + disconnections. + * msg_size is the size of the message. + * msg_fields is the list of parsed header fields of the message. + This can be NULL (see the Section called mailimf_fields - list of + header fields in Chapter 3). + * msg_flags is the flags of the message. This can be NULL (see the + Section called Message flags). + * msg_resolved will tell if the field msg_single_fields has been + initialized. + * msg_single_fields will be filled using msg_fields (see the Section + called mailimf_single_fields - simplified fields in Chapter 3). + * msg_mime is the MIME structure of the message. It is intialized at + least when get_bodystructure() is called once. + * msg_cached is 1 when the message was cached. This is used + internally. + * msg_data is the internal state of the message. The content depends + on the driver. + * msg_folder is used to reference the mailfolder, this is a + workaround due to the problem with initial conception, where + folder notion did not exist. + * msg_user_data is a field for free use. The user can store any data + in that field. + _________________________________________________________________ + +mailmessage_new + +#include <libetpan/libetpan.h> + +mailmessage * mailmessage_new(void); + +void mailmessage_free(mailmessage * info); + + + mailmessage_new() will create a new message (without driver). This is + used internally by drivers. + + mailmessage_free() will free the memory used by the given message. + _________________________________________________________________ + +mailmessage_init + +#include <libetpan/libetpan.h> + +int mailmessage_init(mailmessage * msg_info, + mailsession * session, + mailmessage_driver * driver, + uint32_t index, size_t size); + + + mailmessage_init() will initialize a message with a driver. + + * msg_info is the message to initialize (see the Section called + Message). + * session is the session related to the message (see the Section + called Session). + * driver is the driver to use for the message (see the Section + called Message driver). + * index is the index of the message. + * size is the size of the message. + _________________________________________________________________ + +mailmessage_flush + +#include <libetpan/libetpan.h> + +int mailmessage_flush(mailmessage * info); + + + This function will release the memory used by the MIME structure of + the message. + _________________________________________________________________ + +mailmessage_check + +#include <libetpan/libetpan.h> + +int mailmessage_check(mailmessage * info); + + + After you set some flags, if you want to notify them to the session + before destroying the message, you can use this function. + _________________________________________________________________ + +mailmessage_fetch_result_free + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_result_free(mailmessage * msg_info, + char * msg); + + + This function will free a string returned by any + mailmessage_fetch_XXX() function. + _________________________________________________________________ + +mailmessage_fetch + +#include <libetpan/libetpan.h> + +int mailmessage_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + + + This function returns the content of the message (headers and text). + _________________________________________________________________ + +mailmessage_fetch_header + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + + + This function returns the header of the message as a string. + _________________________________________________________________ + +mailmessage_fetch_body + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + + + This function returns the content of the message (without headers). + _________________________________________________________________ + +mailmessage_fetch_size + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_size(mailmessage * msg_info, + size_t * result); + + + This function returns the size of the message content. + _________________________________________________________________ + +mailmessage_get_bodystructure + +#include <libetpan/libetpan.h> + +int mailmessage_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + + + This functions returns the MIME structure of the message. The returned + information MUST not be freed by hand. It is freed by + mailmessage_flush() or mailmessage_free() (see the Section called + mailmime - MIME part in Chapter 4). + _________________________________________________________________ + +mailmessage_fetch_section + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + + + This function returns the content of a MIME part. + _________________________________________________________________ + +mailmessage_fetch_section_header + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + + This function returns the header of the message contained in the given + MIME part. + _________________________________________________________________ + +mailmessage_fetch_section_mime + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + + This function returns the MIME header of the given MIME part. + _________________________________________________________________ + +mailmessage_fetch_section_body + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + + This function returns the text part of the message contained in the + given MIME part. + _________________________________________________________________ + +mailmessage_fetch_envelope + +#include <libetpan/libetpan.h> + +int mailmessage_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + + _________________________________________________________________ + +mailmessage_get_flags + +#include <libetpan/libetpan.h> + +int mailmessage_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + + + This function returns the flags related to the message. The returned + information MUST not be freed by hand. It is freed by + mailmessage_free(). + _________________________________________________________________ + +mailmessage_resolve_single_fields + +#include <libetpan/libetpan.h> + +void mailmessage_resolve_single_fields(mailmessage * msg_info); + + + This function will use the fields information to fill the + single_fields structure in the mailmessage structure. + _________________________________________________________________ + +Message list + +#include <libetpan/libetpan.h> + +struct mailmessage_list { + carray * msg_tab; /* elements are (mailmessage *) */ +}; + +struct mailmessage_list * mailmessage_list_new(carray * msg_tab); + +void mailmessage_list_free(struct mailmessage_list * env_list); + + + This is a list of messages. + + msg_tab is an array containing the messages (see linkend="carray"). + + mailmessage_list_new() will initialize a list of messages, using a + given array of messages. + + mailmessage_list_free() will free the memory used by the list of + messages. This will also free the messages. + _________________________________________________________________ + +Message tree + +#include <libetpan/libetpan.h> + +struct mailmessage_tree { + struct mailmessage_tree * node_parent; + char * node_msgid; + time_t node_date; + mailmessage * node_msg; + carray * node_children; /* array of (struct mailmessage_tree *) */ + + /* private, used for threading */ + int node_is_reply; + char * node_base_subject; +}; + + +struct mailmessage_tree * +mailmessage_tree_new(char * node_msgid, time_t node_date, + mailmessage * node_msg); + +void mailmessage_tree_free(struct mailmessage_tree * tree); + +void mailmessage_tree_free_recursive(struct mailmessage_tree * tree); + + + This is a node of a tree of messages. + + * node_parent is the parent of this node. + * node_msgid is the content of the field Message-ID of the message. + * node_date is the date in UNIX format. + * node_msg is the message of the node. The message should have the + msg_fields field initialized. + * node_children is the list of children of this node. + * node_is_reply is set to 1 if the message is a reply. + * node_base_subject is the base subject of the message (base subject + is defined in definition of IMAP thread draft). + + mailmessage_tree_new() will initialize a message node. + + mailmessage_tree_free() will release memory used by the node. This + will NOT free the message. + _________________________________________________________________ + +Message flags + +#include <libetpan/libetpan.h> + +enum { + MAIL_FLAG_NEW = 1 << 0, + MAIL_FLAG_SEEN = 1 << 1, + MAIL_FLAG_FLAGGED = 1 << 2, + MAIL_FLAG_DELETED = 1 << 3, + MAIL_FLAG_ANSWERED = 1 << 4, + MAIL_FLAG_FORWARDED = 1 << 5, + MAIL_FLAG_CANCELLED = 1 << 6, +}; + +struct mail_flags { + uint32_t fl_flags; + clist * fl_extension; /* elements are (char *) */ +}; + +struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_ext); + +void mail_flags_free(struct mail_flags * flags); + +int mail_flags_add_extension(struct mail_flags * flags, + char * ext_flag); + +int mail_flags_remove_extension(struct mail_flags * flags, + char * ext_flag); + +int mail_flags_has_extension(struct mail_flags * flags, + char * ext_flag); + + + This is the structure containing the message flags. + + * fl_flags will contain the standards flags. The value will be a + combinaison (with or binary operation) of MAIL_FLAG_XXX values. + * fl_extension will be a list (see the Section called List in + Chapter 2) of strings representing the non-standard flags. + _________________________________________________________________ + +Example + + Example 5-3. use of message +#include <libetpan/libetpan.h> + +#define DEST_CHARSET "iso-8859-1" + +enum { + NO_ERROR, + ERROR_FILE, + ERROR_MEMORY, + ERROR_INVAL, + ERROR_FETCH, +}; + +/* returns TRUE is given MIME part is a text part */ + +int etpan_mime_is_text(struct mailmime * build_info) +{ + if (build_info->mm_type == MAILMIME_SINGLE) { + if (build_info->mm_content_type != NULL) { + if (build_info->mm_content_type->ct_type->tp_type == + MAILMIME_TYPE_DISCRETE_TYPE) { + if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_ +type == + MAILMIME_DISCRETE_TYPE_TEXT) + return 1; + } + } + else + return 1; + } + + return 0; +} + + +/* display content type */ + +int show_part_info(FILE * f, + struct mailmime_single_fields * mime_fields, + struct mailmime_content * content) +{ + char * description; + char * filename; + int col; + int r; + + description = mime_fields->fld_description; + filename = mime_fields->fld_disposition_filename; + + col = 0; + + r = fprintf(f, " [ Part "); + if (r < 0) + goto err; + + if (content != NULL) { + r = mailmime_content_type_write(f, &col, content); + if (r != MAILIMF_NO_ERROR) + goto err; + } + + if (filename != NULL) { + r = fprintf(f, " (%s)", filename); + if (r < 0) + goto err; + } + + if (description != NULL) { + r = fprintf(f, " : %s", description); + if (r < 0) + goto err; + } + + r = fprintf(f, " ]\n\n"); + if (r < 0) + goto err; + + return NO_ERROR; + + err: + return ERROR_FILE; +} + +/* fetch message and decode if it is base64 or quoted-printable */ + +int etpan_fetch_message(mailmessage * msg_info, + struct mailmime * mime_part, + struct mailmime_single_fields * fields, + char ** result, size_t * result_len) +{ + char * data; + size_t len; + int r; + int encoding; + char * decoded; + size_t decoded_len; + size_t cur_token; + int res; + int encoded; + + encoded = 0; + + r = mailmessage_fetch_section(msg_info, + mime_part, &data, &len); + if (r != MAIL_NO_ERROR) { + res = ERROR_FETCH; + goto err; + } + + encoded = 1; + + /* decode message */ + + if (encoded) { + if (fields->fld_encoding != NULL) + encoding = fields->fld_encoding->enc_type; + else + encoding = MAILMIME_MECHANISM_8BIT; + } + else { + encoding = MAILMIME_MECHANISM_8BIT; + } + + cur_token = 0; + r = mailmime_part_parse(data, len, &cur_token, + encoding, &decoded, &decoded_len); + if (r != MAILIMF_NO_ERROR) { + res = ERROR_FETCH; + goto free; + } + + mailmessage_fetch_result_free(msg_info, data); + + * result = decoded; + * result_len = decoded_len; + + return NO_ERROR; + + free: + mailmessage_fetch_result_free(msg_info, data); + err: + return res; +} + +/* fetch fields */ + +struct mailimf_fields * fetch_fields(mailmessage * msg_info, + struct mailmime * mime) +{ + char * data; + size_t len; + int r; + size_t cur_token; + struct mailimf_fields * fields; + + r = mailmessage_fetch_section_header(msg_info, mime, + &data, &len); + if (r != MAIL_NO_ERROR) + return NULL; + + cur_token = 0; + r = mailimf_envelopes_fields_parse(data, len, + &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + mailmessage_fetch_result_free(msg_info, data); + return NULL; + } + + mailmessage_fetch_result_free(msg_info, data); + + return fields; +} + +/* render message */ + +static int etpan_render_mime(FILE * f, mailmessage * msg_info, + struct mailmime * mime) +{ + int r; + clistiter * cur; + int col; + int text; + int show; + struct mailmime_single_fields fields; + int res; + + mailmime_single_fields_init(&fields, mime->mm_mime_fields, + mime->mm_content_type); + + text = etpan_mime_is_text(mime); + + r = show_part_info(f, &fields, mime->mm_content_type); + if (r != NO_ERROR) { + res = r; + goto err; + } + + switch(mime->mm_type) { + case MAILMIME_SINGLE: + show = 0; + if (text) + show = 1; + + if (show) { + char * data; + size_t len; + char * converted; + size_t converted_len; + char * source_charset; + size_t write_len; + + /* viewable part */ + + r = etpan_fetch_message(msg_info, mime, + &fields, &data, &len); + if (r != NO_ERROR) { + res = r; + goto err; + } + + source_charset = fields.fld_content_charset; + if (source_charset == NULL) + source_charset = DEST_CHARSET; + + r = charconv_buffer(source_charset, DEST_CHARSET, + data, len, &converted, &converted_len); + if (r != MAIL_CHARCONV_NO_ERROR) { + + r = fprintf(f, "[ error converting charset from %s to %s ]\n", + source_charset, DEST_CHARSET); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + + write_len = fwrite(data, 1, len, f); + if (write_len != len) { + mailmime_decoded_part_free(data); + res = r; + goto err; + } + } + else { + write_len = fwrite(converted, 1, converted_len, f); + if (write_len != len) { + charconv_buffer_free(converted); + mailmime_decoded_part_free(data); + res = r; + goto err; + } + + charconv_buffer_free(converted); + } + + write_len = fwrite("\r\n\r\n", 1, 4, f); + if (write_len < 4) { + mailmime_decoded_part_free(data); + res = ERROR_FILE; + goto err; + } + + mailmime_decoded_part_free(data); + } + else { + /* not viewable part */ + + r = fprintf(f, " (not shown)\n\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + break; + + case MAILMIME_MULTIPLE: + + if (strcasecmp(mime->mm_content_type->ct_subtype, + "alternative") == 0) { + struct mailmime * prefered_body; + int prefered_score; + + /* case of multiple/alternative */ + + /* + we choose the better part, + alternative preference : + + text/plain => score 3 + text/xxx => score 2 + other => score 1 + */ + + prefered_body = NULL; + prefered_score = 0; + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * submime; + int score; + + score = 1; + submime = clist_content(cur); + if (etpan_mime_is_text(submime)) + score = 2; + + if (submime->mm_content_type != NULL) { + if (strcasecmp(submime->mm_content_type->ct_subtype, + "plain") == 0) + score = 3; + } + + if (score > prefered_score) { + prefered_score = score; + prefered_body = submime; + } + } + + if (prefered_body != NULL) { + r = etpan_render_mime(f, msg_info, prefered_body); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + else { + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + + r = etpan_render_mime(f, msg_info, clist_content(cur)); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + + break; + + case MAILMIME_MESSAGE: + + if (mime->mm_data.mm_message.mm_fields != NULL) { + struct mailimf_fields * fields; + + if (msg_info != NULL) { + fields = fetch_fields(msg_info, mime); + if (fields == NULL) { + res = ERROR_FETCH; + goto err; + } + + col = 0; + r = mailimf_fields_write(f, &col, fields); + if (r != NO_ERROR) { + mailimf_fields_free(fields); + res = r; + goto err; + } + + mailimf_fields_free(fields); + } + else { + col = 0; + r = fields_write(f, &col, mime->mm_data.mm_message.mm_fields); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + r = fprintf(f, "\r\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + r = etpan_render_mime(f, msg_info, + mime->mm_data.mm_message.mm_msg_mime); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + break; + } + + return NO_ERROR; + + err: + return res; +} + + + +int main(void) +{ + struct mailstorage * storage; + int r; + + storage = mailstorage_new(NULL); + + imap_mailstorage_init(storage, "imap.my-servers.org", 0, + NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN, + "my-login", "my-password", 1, "/home/login/.libetpan/cache"); + + r = mailstorage_connect(storage); + if (r == MAIL_NO_ERROR) { + struct mailfolder * folder; + + folder = mailfolder_new(storage, "INBOX", NULL); + + r = mailfolder_connect(folder); + if (r == MAIL_NO_ERROR) { + struct mailmessage_list * msg_list; + mailmessage * msg; + + mailfolder_get_messages_list(folder, &msg_list); + + if (carray_count(msg_list->msg_tab) > 0) { + struct mailmime * mime; + + msg = carray_get(msg_list->msg_tab, 0); + + mailmessage_get_bodystructure(msg, &mime); + + recursive_fetch(msg, mime); + + /* do the things */ + + mailmessage_flush(msg); + } + mailmessage_list_free(msg_list); + + mailfolder_disconnect(folder); + } + + mailstorage_disconnect(storage); + } + + mailstorage_free(storage); +} + + _________________________________________________________________ + +Session + +Session driver + +#include <libetpan/libetpan.h> + +struct mailsession_driver { + char * sess_name; + + int (* sess_initialize)(mailsession * session); + void (* sess_uninitialize)(mailsession * session); + + int (* sess_parameters)(mailsession * session, + int id, void * value); + + int (* sess_connect_stream)(mailsession * session, mailstream * s); + int (* sess_connect_path)(mailsession * session, char * path); + + int (* sess_starttls)(mailsession * session); + + int (* sess_login)(mailsession * session, char * userid, char * password); + int (* sess_logout)(mailsession * session); + int (* sess_noop)(mailsession * session); + + /* folders operations */ + + int (* sess_build_folder_name)(mailsession * session, char * mb, + char * name, char ** result); + + int (* sess_create_folder)(mailsession * session, char * mb); + int (* sess_delete_folder)(mailsession * session, char * mb); + int (* sess_rename_folder)(mailsession * session, char * mb, + char * new_name); + int (* sess_check_folder)(mailsession * session); + int (* sess_examine_folder)(mailsession * session, char * mb); + int (* sess_select_folder)(mailsession * session, char * mb); + int (* sess_expunge_folder)(mailsession * session); + int (* sess_status_folder)(mailsession * session, char * mb, + uint32_t * result_num, uint32_t * result_recent, + uint32_t * result_unseen); + int (* sess_messages_number)(mailsession * session, char * mb, + uint32_t * result); + int (* sess_recent_number)(mailsession * session, char * mb, + uint32_t * result); + int (* sess_unseen_number)(mailsession * session, char * mb, + uint32_t * result); + + int (* sess_list_folders)(mailsession * session, char * mb, + struct mail_list ** result); + int (* sess_lsub_folders)(mailsession * session, char * mb, + struct mail_list ** result); + + int (* sess_subscribe_folder)(mailsession * session, char * mb); + int (* sess_unsubscribe_folder)(mailsession * session, char * mb); + + /* messages operations */ + + int (* sess_append_message)(mailsession * session, + char * message, size_t size); + int (* sess_copy_message)(mailsession * session, + uint32_t num, char * mb); + int (* sess_move_message)(mailsession * session, + uint32_t num, char * mb); + + int (* sess_get_message)(mailsession * session, + uint32_t num, mailmessage ** result); + + int (* sess_get_message_by_uid)(mailsession * session, + const char * uid, mailmessage ** result); + + int (* sess_get_messages_list)(mailsession * session, + struct mailmessage_list ** result); + int (* sess_get_envelopes_list)(mailsession * session, + struct mailmessage_list * env_list); + int (* sess_remove_message)(mailsession * session, uint32_t num); +}; + + + This is a driver for a session. + + * sess_name is the name of the driver. + * sess_initialize() is the function that will initializes a data + structure (field sess_data in the session) specific to the driver. + The field data (field sess_data in the session) is the state of + the session, the internal data structure used by the driver. It is + called when creating the mailsession structure with + mailsession_new(). + * sess_uninitialize() frees the structure created with + sess_initialize() + * sess_parameters() implements functions specific to the given mail + access. + * sess_connect_stream() connects a stream to the session. + * sess_connect_path() notify a main path to the session. + * sess_starttls() changes the current stream to a TLS stream (see + the Section called TLS stream in Chapter 2). + * sess_login() notifies the user and the password to authenticate to + the session. + * sess_logout() exits the session and closes the stream. + * sess_noop() does no operation on the session, but it can be used + to poll for the status of the connection. + * sess_build_folder_name() will return an allocated string with that + contains the complete path of the folder to create. Use of this + method is deprecated. + * sess_create_folder() creates the folder that corresponds to the + given name. Use of this method is deprecated. + * sess_delete_folder() deletes the folder that corresponds to the + given name. Use of this method is deprecated. + * sess_rename_folder() change the name of the folder. Use of this + method is deprecated. + * sess_check_folder() makes a checkpoint of the session. + * sess_examine_folder() selects a mailbox as readonly. Use of this + method is deprecated. + * sess_select_folder() selects a mailbox. + * sess_expunge_folder() deletes all messages marked \Deleted. + * sess_status_folder() queries the status of the folder (number of + messages, number of recent messages, number of unseen messages). + * sess_messages_number() queries the number of messages in the + folder. + * sess_recent_number() queries the number of recent messages in the + folder. + * sess_unseen_number() queries the number of unseen messages in the + folder. + * sess_list_folders() returns the list of all sub-mailboxes of the + given mailbox. Use of this method is deprecated. + * sess_lsub_folders() returns the list of subscribed sub-mailboxes + of the given mailbox. Use of this method is deprecated. + * sess_subscribe_folder() subscribes to the given mailbox. Use of + this method is deprecated. + * sess_unsubscribe_folder() unsubscribes to the given mailbox. Use + of this method is deprecated. + * sess_append_message() adds a RFC 2822 message to the current given + mailbox. + * sess_copy_message() copies a message whose number is given to a + given mailbox. The mailbox must be accessible from the same + session. Use of this method is deprecated. + * sess_move_message() moves a message whose number is given to a + given mailbox. The mailbox must be accessible from the same + session. Use of this method is deprecated. + * sess_get_messages_list() returns the list of message numbers of + the current mailbox (see the Section called Message list). + * sess_get_envelopes_list() fills the parsed fields in the + mailmessage structures (see the Section called Message) of the + mailmessage_list (see the Section called Message list). + * sess_remove_message() removes the given message from the mailbox. + The message is permanently deleted. Use of this method is + deprecated. + * sess_get_message() returns a mailmessage structure (see the + Section called Message) that corresponds to the given message + number. Use of this method is deprecated. + * sess_get_message_by_uid() returns a mailmessage structure (see the + Section called Message) that corresponds to the given message + unique identifier. + + mandatory functions are the following : + + * sess_connect_stream() or connect_path() + * sess_logout() + * sess_get_messages_list() + * sess_get_envelopes_list() + + we advise you to implement these functions : + + * sess_select_folder() (in case a session can access several + folders). + * sess_noop() (to check if the server is responding) + * sess_check_folder() (to make a checkpoint of the session) + * sess_status_folder(), sess_messages_number(), + sess_recent_number(), sess_unseen_number() (to get stat of the + folder) + * sess_append_message() (but can't be done in the case of POP3 at + least). + * sess_login() in a case of an authenticated driver. + * sess_starttls() in a case of a stream driver, if the procotol + supports STARTTLS. + * sess_get_message_by_uid() so that the application can remember the + messages by UID and build its own list of messages. + * Everything that is specific to the driver will be implemented in + sess_parameters(). + _________________________________________________________________ + +Session + +#include <libetpan/libetpan.h> + +struct mailsession { + void * sess_data; + mailsession_driver * sess_driver; +}; + +mailsession * mailsession_new(mailsession_driver * sess_driver); + +void mailsession_free(mailsession * session); + + + This is a session. This is an abstraction used to access the storage, + using the network or the filesystem. + + * sess_data is the state of the session. This is specific to the + driver. + * sess_driver is the driver of the session. + + mailsession_new() will create a new session using the given driver + (sess_driver). + + mailsession_free() will release the memory used by the session. + _________________________________________________________________ + +mailsession_parameters + +#include <libetpan/libetpan.h> + +int mailsession_parameters(mailsession * session, + int id, void * value); + + + This function make calls specific to the driver + _________________________________________________________________ + +mailsession_connect_stream + +#include <libetpan/libetpan.h> + +int mailsession_connect_stream(mailsession * session, mailstream * s); + + + There are drivers of two kinds : stream drivers (driver that connects + to servers through TCP or other means of connection) and file drivers + (driver that are based on filesystem) This function can only be used + by stream drivers and this connects a stream to the session + _________________________________________________________________ + +mailsession_connect_path + +#include <libetpan/libetpan.h> + +int mailsession_connect_path(mailsession * session, char * path); + + + This function can only be used by file drivers and selects the main + path of the session. + _________________________________________________________________ + +mailsession_starttls + +#include <libetpan/libetpan.h> + +int mailsession_starttls(mailsession * session); + + + This switches the current connection to TLS (secure layer). This will + only work with stream drivers. + _________________________________________________________________ + +mailsession_login + +#include <libetpan/libetpan.h> + +int mailsession_login(mailsession * session, + char * userid, char * password); + + + This notifies the login and the password to authenticate to the + session. + _________________________________________________________________ + +mailsession_logout + +#include <libetpan/libetpan.h> + +int mailsession_logout(mailsession * session); + + + This function disconnects the session and closes the stream. + _________________________________________________________________ + +mailsession_noop + +#include <libetpan/libetpan.h> + +int mailsession_noop(mailsession * session); + + + This function does no operation on the session, but it can be used to + poll for the status of the connection. + _________________________________________________________________ + +mailsession_check_folder + +#include <libetpan/libetpan.h> + +int mailsession_check_folder(mailsession * session); + + + This function makes a checkpoint of the session. + _________________________________________________________________ + +mailsession_select_folder + +#include <libetpan/libetpan.h> + +int mailsession_select_folder(mailsession * session, char * mb); + + + This function selects a mailbox. + _________________________________________________________________ + +mailsession_expunge_folder + +#include <libetpan/libetpan.h> + +int mailsession_expunge_folder(mailsession * session); + + + This function deletes all messages marked for deletion. + _________________________________________________________________ + +mailsession_status_folder + +#include <libetpan/libetpan.h> + +int mailsession_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + + + This function queries the status of the folder (number of messages, + number of recent messages, number of unseen messages). + _________________________________________________________________ + +mailsession_messages_number + +#include <libetpan/libetpan.h> + +int mailsession_messages_number(mailsession * session, char * mb, + uint32_t * result); + + + This function queries the number of messages in the folder. + _________________________________________________________________ + +mailsession_recent_number + +#include <libetpan/libetpan.h> + +int mailsession_recent_number(mailsession * session, + char * mb, uint32_t * result); + + + This function queries the number of recent messages in the folder. + _________________________________________________________________ + +mailsession_unseen_number + +#include <libetpan/libetpan.h> + +int mailsession_unseen_number(mailsession * session, char * mb, + uint32_t * result); + + + This function queries the number of unseen messages in the folder. + _________________________________________________________________ + +mailsession_append_message + +#include <libetpan/libetpan.h> + +int mailsession_append_message(mailsession * session, + char * message, size_t size); + + + This adds a RFC 2822 message to the current mailbox. + _________________________________________________________________ + +mailsession_get_messages_list + +#include <libetpan/libetpan.h> + +int mailsession_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + + + This function returns the list of messages of the current mailbox. + _________________________________________________________________ + +mailsession_get_envelopes_list + +#include <libetpan/libetpan.h> + +int mailsession_get_envelopes_list(mailsession * session, + struct mailmessage_list * result); + + + This function fills the parsed fields in the mailmessage structures + (see the Section called Message) of the mailmessage_list (see the + Section called Message list). + _________________________________________________________________ + +mailsession_get_message + +#include <libetpan/libetpan.h> + +int mailsession_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + + + This function returns a mailmessage (see the Section called Message) + structure that corresponds to the given message number. + + Warning + + mailsession_get_message_by_uid() should be used instead. + _________________________________________________________________ + +mailsession_get_message_by_uid + +#include <libetpan/libetpan.h> + +int mailsession_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + + + This function returns a mailmessage structure that corresponds to the + given message unique identifier. This is currently implemented only + for cached drivers. + + Warning + + That deprecates the use of mailsession_get_message(). Added: freeswitch/trunk/libs/libetpan/doc/API/book1.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/book1.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1841 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>libEtPan! API</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="NEXT" +TITLE="Introduction" +HREF="c13.htm"></HEAD +><BODY +CLASS="BOOK" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="BOOK" +><A +NAME="LIBETPAN-API" +></A +><DIV +CLASS="TITLEPAGE" +><H1 +CLASS="TITLE" +><A +NAME="AEN2" +>libEtPan! API</A +></H1 +><H3 +CLASS="AUTHOR" +><A +NAME="AEN6" +></A +>Viet Hoa DINH</H3 +><P +CLASS="COPYRIGHT" +>Copyright © 2003 DINH Viet Hoa</P +><HR></DIV +><DIV +CLASS="TOC" +><DL +><DT +><B +>Table of Contents</B +></DT +><DT +>1. <A +HREF="c13.htm" +>Introduction</A +></DT +><DT +>2. <A +HREF="c16.htm" +>Tools and datatypes</A +></DT +><DD +><DL +><DT +><A +HREF="c16.htm#AEN19" +>Array</A +></DT +><DD +><DL +><DT +><A +HREF="c16.htm#CARRAY-NEW" +>carray_new and carray_free</A +></DT +><DT +><A +HREF="c16.htm#CARRAY-SET-SIZE" +>carray_set_size</A +></DT +><DT +><A +HREF="c16.htm#CARRAY-COUNT" +>carray_count, carray_add, carray_get and carray_set</A +></DT +><DT +><A +HREF="c16.htm#CARRAY-DELETE" +>carray_delete</A +></DT +><DT +><A +HREF="c16.htm#CARRAY-DATA" +>carray_data</A +></DT +></DL +></DD +><DT +><A +HREF="x88.htm" +>List</A +></DT +><DD +><DL +><DT +><A +HREF="x88.htm#CLIST-NEW" +>clist_new and clist_free</A +></DT +><DT +><A +HREF="x88.htm#CLIST-COUNT" +>clist_isempty and clist_count</A +></DT +><DT +><A +HREF="x88.htm#CLIST-BEGIN" +>running through clist</A +></DT +><DT +><A +HREF="x88.htm#CLIST-APPEND" +>clist modification</A +></DT +><DT +><A +HREF="x88.htm#CLIST-FOREACH" +>clist_foreach</A +></DT +><DT +><A +HREF="x88.htm#CLIST-CONCAT" +>clist_concat</A +></DT +></DL +></DD +><DT +><A +HREF="x161.htm" +>Hash table</A +></DT +><DD +><DL +><DT +><A +HREF="x161.htm#CHASH-NEW" +>chash_new and chash_free</A +></DT +><DT +><A +HREF="x161.htm#CHASH-GET" +>chash_set and chash_get</A +></DT +><DT +><A +HREF="x161.htm#CHASH-DELETE" +>chash_delete</A +></DT +><DT +><A +HREF="x161.htm#CHASH-RESIZE" +>chash_resize</A +></DT +><DT +><A +HREF="x161.htm#CHASH-BEGIN" +>running through the chash</A +></DT +><DT +><A +HREF="x161.htm#CHASH-COUNT" +>chash_size and chash_count</A +></DT +></DL +></DD +><DT +><A +HREF="x229.htm" +>Buffered I/O</A +></DT +><DD +><DL +><DT +><A +HREF="x229.htm#MAILSTREAM-SOCKET" +>socket stream</A +></DT +><DT +><A +HREF="x229.htm#MAILSTREAM-SSL" +>TLS stream</A +></DT +></DL +></DD +><DT +><A +HREF="x289.htm" +>non-buffered I/O</A +></DT +><DT +><A +HREF="x312.htm" +>strings</A +></DT +><DD +><DL +><DT +><A +HREF="x312.htm#MMAP-STRING-NEW" +>constructor and destructor</A +></DT +><DT +><A +HREF="x312.htm#MMAP-STRING-ASSIGN" +>string value modification</A +></DT +><DT +><A +HREF="x312.htm#MMAP-STRING-APPEND" +>insertion in string, deletion in string</A +></DT +><DT +><A +HREF="x312.htm#MMAP-STRING-REF" +>referencing string</A +></DT +></DL +></DD +></DL +></DD +><DT +>3. <A +HREF="c385.htm" +>Internet Message Format</A +></DT +><DD +><DL +><DT +><A +HREF="c385.htm#AEN397" +>Quick start</A +></DT +><DD +><DL +><DT +><A +HREF="c385.htm#AEN400" +>Parse message headers</A +></DT +><DT +><A +HREF="c385.htm#AEN420" +>Render the message headers</A +></DT +></DL +></DD +><DT +><A +HREF="x425.htm" +>Data types</A +></DT +><DD +><DL +><DT +><A +HREF="x425.htm#MAILIMF-MAILBOX" +>mailimf_mailbox - mailbox</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-ADDRESS" +>mailimf_address - address</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-MAILBOX-LIST" +>mailimf_mailbox_list - list of mailboxes</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-ADDRESS-LIST" +>mailimf_address_list - list of addresses</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-GROUP" +>mailimf_group - named group of mailboxes</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-DATE-TIME" +>mailimf_date_time - date of a message</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-ORIG-DATE" +>mailimf_orig_date - parsed content of date header</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-FROM" +>mailimf_from - parsed content of From header</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-SENDER" +>mailimf_sender - parsed content of Sender header</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-REPLY-TO" +>mailimf_reply_to - parsed content of Reply-To header</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-TO" +>mailimf_to - parsed content of To header</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-CC" +>mailimf_cc - parsed content of Cc</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-BCC" +>mailimf_bcc - parsed content of Bcc field</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-MESSAGE-ID" +>mailimf_message_id - parsed content of Message-ID header</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-IN-REPLY-TO" +>mailimf_in_reply_to - parsed content of In-Reply-To + field</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-REFERENCES" +>mailimf_references - parsed content of References field</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-SUBJECT" +>mailimf_subject - parsed content of Subject field</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-COMMENTS" +>mailimf_comments - parsed content of Comments field</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-KEYWORDS" +>mailimf_keywords - parsed content of Keywords field</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-RETURN" +>mailimf_return - parsed content of Return-Path field</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-PATH" +>mailimf_path - address in Return-Path field</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-OPTIONAL-FIELD" +>mailimf_optional_field - non-standard header</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-FIELD" +>mailimf_field - header field</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-FIELDS" +>mailimf_fields - list of header fields</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-BODY" +>mailimf_body - message body without headers</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-MESSAGE" +>mailimf_message - parsed message</A +></DT +><DT +><A +HREF="x425.htm#MAILIMF-SINGLE-FIELDS" +>mailimf_single_fields - simplified fields</A +></DT +></DL +></DD +><DT +><A +HREF="x1094.htm" +>Parser functions</A +></DT +><DD +><DL +><DT +><A +HREF="x1094.htm#MAILIMF-ADDRESS-LIST-PARSE" +>mailimf_address_list_parse</A +></DT +><DT +><A +HREF="x1094.htm#MAILIMF-ADDRESS-PARSE" +>mailimf_address_parse</A +></DT +><DT +><A +HREF="x1094.htm#MAILIMF-BODY-PARSE" +>mailimf_body_parse</A +></DT +><DT +><A +HREF="x1094.htm#MAILIMF-ENVELOPE-AND-OPTIONAL-FIELDS-PARSE" +>mailimf_envelope_and_optional_fields_parse</A +></DT +><DT +><A +HREF="x1094.htm#MAILIMF-ENVELOPE-FIELDS-PARSE" +>mailimf_envelope_fields_parse</A +></DT +><DT +><A +HREF="x1094.htm#MAILIMF-OPTIONAL-FIELDS-PARSE" +>mailimf_optional_fields_parse</A +></DT +><DT +><A +HREF="x1094.htm#MAILIMF-FIELDS-PARSE" +>mailimf_fields_parse</A +></DT +><DT +><A +HREF="x1094.htm#MAILIMF-IGNORE-FIELD-PARSE" +>mailimf_ignore_field_parse</A +></DT +><DT +><A +HREF="x1094.htm#MAILIMF-MAILBOX-LIST-PARSE" +>mailimf_mailbox_list_parse</A +></DT +><DT +><A +HREF="x1094.htm#MAILIMF-MAILBOX-PARSE" +>mailimf_mailbox_parse</A +></DT +><DT +><A +HREF="x1094.htm#MAILIMF-MESSAGE-PARSE" +>mailimf_message_parse</A +></DT +></DL +></DD +><DT +><A +HREF="x1381.htm" +>Creation functions</A +></DT +><DD +><DL +><DT +><A +HREF="x1381.htm#MAILIMF-MAILBOX-LIST-ADD" +>mailimf_mailbox_list</A +></DT +><DT +><A +HREF="x1381.htm#MAILIMF-ADDRESS-LIST-ADD" +>mailimf_address_list</A +></DT +><DT +><A +HREF="x1381.htm#MAILIMF-FIELDS-ADD" +>mailimf_fields</A +></DT +></DL +></DD +><DT +><A +HREF="x1556.htm" +>Rendering of messages</A +></DT +><DD +><DL +><DT +><A +HREF="x1556.htm#MAILIMF-FIELDS-WRITE" +>Header fields</A +></DT +></DL +></DD +></DL +></DD +><DT +>4. <A +HREF="c1586.htm" +>MIME</A +></DT +><DD +><DL +><DT +><A +HREF="c1586.htm#AEN1598" +>Quick start</A +></DT +><DD +><DL +><DT +><A +HREF="c1586.htm#AEN1601" +>Parse MIME message</A +></DT +><DT +><A +HREF="c1586.htm#AEN1609" +>Render the MIME message</A +></DT +></DL +></DD +><DT +><A +HREF="x1614.htm" +>Data types</A +></DT +><DD +><DL +><DT +><A +HREF="x1614.htm#MAILMIME-COMPOSITE-TYPE" +>mailmime_composite_type - Composite MIME type</A +></DT +><DT +><A +HREF="x1614.htm#MAILMIME-CONTENT" +>mailmime_content - MIME content type (Content-Type)</A +></DT +><DT +><A +HREF="x1614.htm#MAILMIME-DISCRETE-TYPE" +>mailmime_discrete_type - MIME discrete type</A +></DT +><DT +><A +HREF="x1614.htm#MAILMIME-FIELD" +>mailmime_field - MIME header field</A +></DT +><DT +><A +HREF="x1614.htm#MAILMIME-MECHANISM" +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</A +></DT +><DT +><A +HREF="x1614.htm#MAILMIME-FIELDS" +>mailmime_fields - header fields</A +></DT +><DT +><A +HREF="x1614.htm#MAILMIME-PARAMETER" +>mailmime_parameter - MIME type parameter</A +></DT +><DT +><A +HREF="x1614.htm#MAILMIME-TYPE" +>mailmime_type - MIME main type</A +></DT +><DT +><A +HREF="x1614.htm#MAILMIME-LANGUAGE" +>mailmime_language - Language of MIME part</A +></DT +><DT +><A +HREF="x1614.htm#MAILMIME-DATA" +>mailmime_data - Content of MIME part</A +></DT +><DT +><A +HREF="x1614.htm#MAILMIME" +>mailmime - MIME part</A +></DT +><DT +><A +HREF="x1614.htm#MAILMIME-DISPOSITION" +>mailmime_disposition - MIME disposition information (Content-Disposition)</A +></DT +><DT +><A +HREF="x1614.htm#MAILMIME-DISPOSITION-TYPE" +>mailmime_disposition_type - Type of MIME disposition</A +></DT +><DT +><A +HREF="x1614.htm#MAILMIME-DISPOSITION-PARM" +>mailmime_disposition_parm - MIME disposition parameter</A +></DT +><DT +><A +HREF="x1614.htm#MAILMIME-SINGLE-FIELDS" +>mailmime_single_fields - MIME headers</A +></DT +></DL +></DD +><DT +><A +HREF="x2180.htm" +>Parser functions</A +></DT +><DD +><DL +><DT +><A +HREF="x2180.htm#MAILMIME-CONTENT-PARSE" +>mailmime_content_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-DESCRIPTION-PARSE" +>mailmime_description_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-ENCODING-PARSE" +>mailmime_encoding_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-FIELD-PARSE" +>mailmime_field_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-ID-PARSE" +>mailmime_id_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-FIELDS-PARSE" +>mailmime_fields_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-VERSION-PARSE" +>mailmime_version_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-PARAMETER-PARSE" +>mailmime_parameter_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-LANGUAGE-PARSE" +>mailmime_language_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-DISPOSITION-PARSE" +>mailmime_disposition_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-DISPOSITION-TYPE-PARSE" +>mailmime_disposition_type_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-ENCODED-PHRASE-PARSE" +>mailmime_encoded_phrase_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-PARSE" +>mailmime_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-BASE64-BODY-PARSE" +>mailmime_base64_body_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-QUOTED-PRINTABLE-BODY-PARSE" +>mailmime_quoted_printable_body_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-BINARY-BODY-PARSE" +>mailmime_binary_body_parse</A +></DT +><DT +><A +HREF="x2180.htm#MAILMIME-PART-PARSE" +>mailmime_part_parse</A +></DT +></DL +></DD +><DT +><A +HREF="x2583.htm" +>Rendering of MIME parts</A +></DT +><DD +><DL +><DT +><A +HREF="x2583.htm#MAILMIME-FIELDS-WRITE" +>mailmime_fields_write, mailmime_content_write and + mailmime_content_type_write</A +></DT +><DT +><A +HREF="x2583.htm#MAILMIME-WRITE" +>mailmime_write</A +></DT +><DT +><A +HREF="x2583.htm#MAILMIME-QUOTED-PRINTABLE-WRITE" +>mailmime_quoted_printable_write + and mailmime_base64_write</A +></DT +><DT +><A +HREF="x2583.htm#MAILMIME-DATA-WRITE" +>mailmime_data_write</A +></DT +></DL +></DD +><DT +><A +HREF="x2669.htm" +>Creation functions</A +></DT +><DD +><DL +><DT +><A +HREF="x2669.htm#MAILMIME-DISPOSITION-NEW-FILENAME" +>mailmime_disposition_new_filename and + mailmime_disposition_new_with_data</A +></DT +><DT +><A +HREF="x2669.htm#MAILMIME-FIELDS-NEW-EMPTY" +>mailmime_fields_new_empty and mailmime_fields_add</A +></DT +><DT +><A +HREF="x2669.htm#MAILMIME-FIELDS-NEW-WITH-DATA" +>mailmime_fields_new_with_data and + mailmime_fields_new_with_version</A +></DT +><DT +><A +HREF="x2669.htm#MAILMIME-GET-CONTENT-MESSAGE" +>mailmime_get_content_message</A +></DT +><DT +><A +HREF="x2669.htm#MAILMIME-DATA-NEW-DATA" +>mailmime_data_new_data and mailmime_data_new_file</A +></DT +><DT +><A +HREF="x2669.htm#MAILMIME-NEW-MESSAGE-DATA" +>mailmime_new_message_data, mailmime_new_empty and + mailmime_new_with_content</A +></DT +><DT +><A +HREF="x2669.htm#MAILMIME-SET-PREAMBLE-FILE" +>mailmime_set_preamble_file, mailmime_set_epilogue_file, + mailmime_set_preamble_text and mailmime_set_epilogue_text</A +></DT +><DT +><A +HREF="x2669.htm#MAILMIME-SET-BODY-FILE" +>mailmime_set_body_file and mailmime_set_body_text</A +></DT +><DT +><A +HREF="x2669.htm#MAILMIME-ADD-PART" +>mailmime_add_part, mailmime_remove_part, + mailmime_smart_add_part and mailmime_smart_remove_part</A +></DT +><DT +><A +HREF="x2669.htm#MAILMIME-SET-IMF-FIELDS" +>mailmime_set_imf_fields</A +></DT +><DT +><A +HREF="x2669.htm#MAILMIME-FIELDS-NEW-ENCODING" +>mailmime_fields_new_encoding and + mailmime_fields_new_filename</A +></DT +></DL +></DD +><DT +><A +HREF="x2946.htm" +>Helper functions</A +></DT +><DD +><DL +><DT +><A +HREF="x2946.htm#MAILMIME-TRANSFER-ENCODING-GET" +>mailmime_transfer_encoding_get</A +></DT +><DT +><A +HREF="x2946.htm#MAILMIME-CONTENT-CHARSET-GET" +>mailmime_content_charset_get and + mailmime_content_param_get</A +></DT +></DL +></DD +></DL +></DD +><DT +>5. <A +HREF="c2988.htm" +>Storages, folders, messages</A +></DT +><DD +><DL +><DT +><A +HREF="c2988.htm#AEN2990" +>Introduction</A +></DT +><DD +><DL +><DT +><A +HREF="c2988.htm#AEN2993" +>Message</A +></DT +><DT +><A +HREF="c2988.htm#AEN2996" +>MIME part</A +></DT +><DT +><A +HREF="c2988.htm#AEN2999" +>Mailbox</A +></DT +><DT +><A +HREF="c2988.htm#AEN3002" +>Storage</A +></DT +><DT +><A +HREF="c2988.htm#AEN3005" +>Folder</A +></DT +><DT +><A +HREF="c2988.htm#AEN3008" +>Session</A +></DT +></DL +></DD +><DT +><A +HREF="x3011.htm" +>Error codes</A +></DT +><DT +><A +HREF="x3015.htm" +>Storage</A +></DT +><DD +><DL +><DT +><A +HREF="x3015.htm#MAILSTORAGE-DRIVER" +>Storage driver</A +></DT +><DT +><A +HREF="x3015.htm#MAILSTORAGE" +>Storage</A +></DT +><DT +><A +HREF="x3015.htm#MAILSTORAGE-NEW" +>mailstorage_new and mailstorage_free</A +></DT +><DT +><A +HREF="x3015.htm#MAILSTORAGE-CONNECT" +>mailstorage_connect and mailstorage_disconnect</A +></DT +><DT +><A +HREF="x3015.htm#AEN3074" +>IMAP storage</A +></DT +><DT +><A +HREF="x3015.htm#AEN3077" +>Example</A +></DT +></DL +></DD +><DT +><A +HREF="x3082.htm" +>Folder</A +></DT +><DD +><DL +><DT +><A +HREF="x3082.htm#MAILFOLDER-DRIVER" +>Folder driver</A +></DT +><DT +><A +HREF="x3082.htm#AEN3095" +>Folder</A +></DT +><DT +><A +HREF="x3082.htm#MAILFOLDER-NEW" +>mailfolder_new and mail_folder_free</A +></DT +><DT +><A +HREF="x3082.htm#MAILFOLDER-CONNECT" +>mailfolder_connect and mailfolder_disconnect</A +></DT +><DT +><A +HREF="x3082.htm#MAILFOLDER-NOOP" +>mailfolder_noop</A +></DT +><DT +><A +HREF="x3082.htm#MAILFOLDER-CHECK" +>mailfolder_check</A +></DT +><DT +><A +HREF="x3082.htm#MAILFOLDER-EXPUNGE" +>mailfolder_expunge</A +></DT +><DT +><A +HREF="x3082.htm#MAILFOLDER-STATUS" +>mailfolder_status</A +></DT +><DT +><A +HREF="x3082.htm#MAILFOLDER-APPEND-MESSAGE" +>mailfolder_append_message</A +></DT +><DT +><A +HREF="x3082.htm#MAILFOLDER-GET-MESSAGES-LIST" +>mailfolder_get_messages_list</A +></DT +><DT +><A +HREF="x3082.htm#MAILFOLDER-GET-ENVELOPES-LIST" +>mailfolder_get_envelopes_list</A +></DT +><DT +><A +HREF="x3082.htm#MAILFOLDER-GET-MESSAGE" +>mailfolder_get_message</A +></DT +><DT +><A +HREF="x3082.htm#MAILFOLDER-GET-MESSAGE-BY-UID" +>mailfolder_get_message_by_uid</A +></DT +><DT +><A +HREF="x3082.htm#AEN3193" +>Example</A +></DT +></DL +></DD +><DT +><A +HREF="x3198.htm" +>Message</A +></DT +><DD +><DL +><DT +><A +HREF="x3198.htm#MAILMESSAGE-DRIVER" +>Message driver</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE" +>Message</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-NEW" +>mailmessage_new</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-INIT" +>mailmessage_init</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-FLUSH" +>mailmessage_flush</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-CHECK" +>mailmessage_check</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-FETCH-RESULT-FREE" +>mailmessage_fetch_result_free</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-FETCH" +>mailmessage_fetch</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-FETCH-HEADER" +>mailmessage_fetch_header</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-FETCH-BODY" +>mailmessage_fetch_body</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-FETCH-SIZE" +>mailmessage_fetch_size</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-GET-BODYSTRUCTURE" +>mailmessage_get_bodystructure</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-FETCH-SECTION" +>mailmessage_fetch_section</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-FETCH-SECTION-HEADER" +>mailmessage_fetch_section_header</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-FETCH-SECTION-MIME" +>mailmessage_fetch_section_mime</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-FETCH-SECTION-BODY" +>mailmessage_fetch_section_body</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-FETCH-ENVELOPE" +>mailmessage_fetch_envelope</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-GET-FLAGS" +>mailmessage_get_flags</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-RESOLVE-SINGLE-FIELDS" +>mailmessage_resolve_single_fields</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-LIST" +>Message list</A +></DT +><DT +><A +HREF="x3198.htm#MAILMESSAGE-TREE" +>Message tree</A +></DT +><DT +><A +HREF="x3198.htm#MAIL-FLAGS" +>Message flags</A +></DT +><DT +><A +HREF="x3198.htm#AEN3467" +>Example</A +></DT +></DL +></DD +><DT +><A +HREF="x3472.htm" +>Session</A +></DT +><DD +><DL +><DT +><A +HREF="x3472.htm#MAILSESSION-DRIVER" +>Session driver</A +></DT +><DT +><A +HREF="x3472.htm#MAILSESSION" +>Session</A +></DT +><DT +><A +HREF="x3472.htm#AEN3670" +>mailsession_parameters</A +></DT +><DT +><A +HREF="x3472.htm#AEN3674" +>mailsession_connect_stream</A +></DT +><DT +><A +HREF="x3472.htm#AEN3678" +>mailsession_connect_path</A +></DT +><DT +><A +HREF="x3472.htm#AEN3682" +>mailsession_starttls</A +></DT +><DT +><A +HREF="x3472.htm#AEN3686" +>mailsession_login</A +></DT +><DT +><A +HREF="x3472.htm#AEN3690" +>mailsession_logout</A +></DT +><DT +><A +HREF="x3472.htm#AEN3694" +>mailsession_noop</A +></DT +><DT +><A +HREF="x3472.htm#AEN3698" +>mailsession_check_folder</A +></DT +><DT +><A +HREF="x3472.htm#AEN3702" +>mailsession_select_folder</A +></DT +><DT +><A +HREF="x3472.htm#AEN3706" +>mailsession_expunge_folder</A +></DT +><DT +><A +HREF="x3472.htm#AEN3710" +>mailsession_status_folder</A +></DT +><DT +><A +HREF="x3472.htm#AEN3714" +>mailsession_messages_number</A +></DT +><DT +><A +HREF="x3472.htm#AEN3718" +>mailsession_recent_number</A +></DT +><DT +><A +HREF="x3472.htm#AEN3722" +>mailsession_unseen_number</A +></DT +><DT +><A +HREF="x3472.htm#AEN3726" +>mailsession_append_message</A +></DT +><DT +><A +HREF="x3472.htm#AEN3730" +>mailsession_get_messages_list</A +></DT +><DT +><A +HREF="x3472.htm#AEN3734" +>mailsession_get_envelopes_list</A +></DT +><DT +><A +HREF="x3472.htm#AEN3741" +>mailsession_get_message</A +></DT +><DT +><A +HREF="x3472.htm#AEN3750" +>mailsession_get_message_by_uid</A +></DT +></DL +></DD +></DL +></DD +></DL +></DIV +><DIV +CLASS="LOT" +><DL +CLASS="LOT" +><DT +><B +>List of Examples</B +></DT +><DT +>2-1. <A +HREF="c16.htm#AEN35" +>carray creation</A +></DT +><DT +>2-2. <A +HREF="c16.htm#AEN45" +>preallocating carray</A +></DT +><DT +>2-3. <A +HREF="c16.htm#AEN66" +>carray access</A +></DT +><DT +>2-4. <A +HREF="c16.htm#AEN79" +>deletion in carray</A +></DT +><DT +>2-5. <A +HREF="x88.htm#AEN101" +>clist creation</A +></DT +><DT +>2-6. <A +HREF="x88.htm#AEN129" +>displaying content of clist</A +></DT +><DT +>2-7. <A +HREF="x88.htm#AEN145" +>deleting elements in a clist</A +></DT +><DT +>2-8. <A +HREF="x88.htm#AEN158" +>merging two clists</A +></DT +><DT +>2-9. <A +HREF="x161.htm#AEN191" +>chash insert and lookup</A +></DT +><DT +>2-10. <A +HREF="x161.htm#AEN198" +>key deletion in a chash</A +></DT +><DT +>2-11. <A +HREF="x161.htm#AEN219" +>running through a chash</A +></DT +><DT +>3-1. <A +HREF="x425.htm#AEN431" +>example of mailbox</A +></DT +><DT +>3-2. <A +HREF="x425.htm#AEN438" +>mailbox creation and display</A +></DT +><DT +>3-3. <A +HREF="x425.htm#AEN465" +>address creation and display</A +></DT +><DT +>3-4. <A +HREF="x425.htm#AEN480" +>Creation and display of mailimf_mailbox_list</A +></DT +><DT +>3-5. <A +HREF="x425.htm#AEN495" +>creation and display of list of addresses</A +></DT +><DT +>3-6. <A +HREF="x425.htm#AEN502" +>example of group</A +></DT +><DT +>3-7. <A +HREF="x425.htm#AEN515" +>creation and display of a group</A +></DT +><DT +>3-8. <A +HREF="x425.htm#AEN522" +>example of date</A +></DT +><DT +>3-9. <A +HREF="x425.htm#AEN553" +>creation and display of date</A +></DT +><DT +>3-10. <A +HREF="x425.htm#AEN569" +>creation and display of Date field</A +></DT +><DT +>3-11. <A +HREF="x425.htm#AEN585" +>creation and display of a From header</A +></DT +><DT +>3-12. <A +HREF="x425.htm#AEN601" +>creation and display of Sender field</A +></DT +><DT +>3-13. <A +HREF="x425.htm#AEN616" +>creation and display of Reply-To field</A +></DT +><DT +>3-14. <A +HREF="x425.htm#AEN632" +>creation and display of To field</A +></DT +><DT +>3-15. <A +HREF="x425.htm#AEN648" +>creation and display of Cc field</A +></DT +><DT +>3-16. <A +HREF="x425.htm#AEN664" +>creation and display of Bcc field</A +></DT +><DT +>3-17. <A +HREF="x425.htm#AEN673" +>example of Message-ID</A +></DT +><DT +>3-18. <A +HREF="x425.htm#AEN684" +>creation and display of Message-ID field</A +></DT +><DT +>3-19. <A +HREF="x425.htm#AEN702" +>creation and display of In-Reply-To field</A +></DT +><DT +>3-20. <A +HREF="x425.htm#AEN720" +>creation and display of References field</A +></DT +><DT +>3-21. <A +HREF="x425.htm#AEN734" +>creation and display of Subject field</A +></DT +><DT +>3-22. <A +HREF="x425.htm#AEN748" +>creation and display of Comment field</A +></DT +><DT +>3-23. <A +HREF="x425.htm#AEN763" +>creation and display of Keywords field</A +></DT +><DT +>3-24. <A +HREF="x425.htm#AEN778" +>creation and display of Return-Path field</A +></DT +><DT +>3-25. <A +HREF="x425.htm#AEN794" +>Creation and display of return path</A +></DT +><DT +>3-26. <A +HREF="x425.htm#AEN814" +>creation and display of non-standard fields</A +></DT +><DT +>3-27. <A +HREF="x425.htm#AEN961" +>creation and display of field</A +></DT +><DT +>3-28. <A +HREF="x425.htm#AEN977" +>creation and display of header fields</A +></DT +><DT +>3-29. <A +HREF="x425.htm#AEN997" +>creation and display of message body</A +></DT +><DT +>3-30. <A +HREF="x425.htm#AEN1017" +>creation and display of message</A +></DT +><DT +>3-31. <A +HREF="x425.htm#AEN1088" +>using mailimf_single_fields</A +></DT +><DT +>3-32. <A +HREF="x425.htm#AEN1091" +>using mailimf_single_fields without memory allocation</A +></DT +><DT +>3-33. <A +HREF="x1094.htm#AEN1120" +>parsing a list of addresses</A +></DT +><DT +>3-34. <A +HREF="x1094.htm#AEN1147" +>parsing an address</A +></DT +><DT +>3-35. <A +HREF="x1094.htm#AEN1174" +>parsing a message body</A +></DT +><DT +>3-36. <A +HREF="x1094.htm#AEN1201" +>parsing commonly used fields and return other fields + in a non-parsed form</A +></DT +><DT +>3-37. <A +HREF="x1094.htm#AEN1228" +>parsing commonly used fields</A +></DT +><DT +>3-38. <A +HREF="x1094.htm#AEN1255" +>parsing optional fields</A +></DT +><DT +>3-39. <A +HREF="x1094.htm#AEN1282" +>parsing header fields</A +></DT +><DT +>3-40. <A +HREF="x1094.htm#AEN1304" +>skipping fields</A +></DT +><DT +>3-41. <A +HREF="x1094.htm#AEN1329" +>parsing a list of mailboxes</A +></DT +><DT +>3-42. <A +HREF="x1094.htm#AEN1354" +>parsing a mailbox</A +></DT +><DT +>3-43. <A +HREF="x1094.htm#AEN1378" +>parsing a message</A +></DT +><DT +>3-44. <A +HREF="x1381.htm#AEN1411" +>creating a list of mailboxes</A +></DT +><DT +>3-45. <A +HREF="x1381.htm#AEN1553" +>creation of header fields</A +></DT +><DT +>3-46. <A +HREF="x1556.htm#AEN1583" +>rendering of fields</A +></DT +><DT +>4-1. <A +HREF="x1614.htm#AEN1635" +>create and display MIME composite type</A +></DT +><DT +>4-2. <A +HREF="x1614.htm#AEN1667" +>Creation and display of MIME content type</A +></DT +><DT +>4-3. <A +HREF="x1614.htm#AEN1691" +>Creation and display of MIME discrete type</A +></DT +><DT +>4-4. <A +HREF="x1614.htm#AEN1757" +>Creation and display of MIME header field</A +></DT +><DT +>4-5. <A +HREF="x1614.htm#AEN1784" +>Creation and display of MIME transfer encoding mechanism</A +></DT +><DT +>4-6. <A +HREF="x1614.htm#AEN1799" +>Creation and display of MIME fields</A +></DT +><DT +>4-7. <A +HREF="x1614.htm#AEN1821" +>Creation and display of MIME type parameter</A +></DT +><DT +>4-8. <A +HREF="x1614.htm#AEN1851" +>Creation and display of MIME main type</A +></DT +><DT +>4-9. <A +HREF="x1614.htm#AEN1864" +>Creation and display of language of MIME part</A +></DT +><DT +>4-10. <A +HREF="x1614.htm#AEN1906" +>Creation and display of MIME part content</A +></DT +><DT +>4-11. <A +HREF="x1614.htm#AEN2007" +>Creation and display of MIME part</A +></DT +><DT +>4-12. <A +HREF="x1614.htm#AEN2026" +>Creation and display of MIME disposition information</A +></DT +><DT +>4-13. <A +HREF="x1614.htm#AEN2041" +>Creation and display of MIME disposition type</A +></DT +><DT +>4-14. <A +HREF="x1614.htm#AEN2090" +>Creation and display of MIME disposition + parameter</A +></DT +><DT +>4-15. <A +HREF="x1614.htm#AEN2177" +>Creation and display of single fields</A +></DT +><DT +>4-16. <A +HREF="x2180.htm#AEN2203" +>Parsing MIME content type</A +></DT +><DT +>4-17. <A +HREF="x2180.htm#AEN2227" +>Parsing MIME description</A +></DT +><DT +>4-18. <A +HREF="x2180.htm#AEN2251" +>parsing MIME encoding mechanism</A +></DT +><DT +>4-19. <A +HREF="x2180.htm#AEN2267" +>parsing MIME header field</A +></DT +><DT +>4-20. <A +HREF="x2180.htm#AEN2291" +>Parsing MIME content identifier</A +></DT +><DT +>4-21. <A +HREF="x2180.htm#AEN2307" +>parsing MIME header fields</A +></DT +><DT +>4-22. <A +HREF="x2180.htm#AEN2331" +>parsing MIME version</A +></DT +><DT +>4-23. <A +HREF="x2180.htm#AEN2356" +>parsing a MIME parameter</A +></DT +><DT +>4-24. <A +HREF="x2180.htm#AEN2380" +>Parsing the MIME content langage</A +></DT +><DT +>4-25. <A +HREF="x2180.htm#AEN2404" +>Parsing the MIME content disposition</A +></DT +><DT +>4-26. <A +HREF="x2180.htm#AEN2427" +>parsing a MIME content disposition type</A +></DT +><DT +>4-27. <A +HREF="x2180.htm#AEN2455" +>decoding a MIME encoded header string</A +></DT +><DT +>4-28. <A +HREF="x2180.htm#AEN2478" +>parsing a MIME message</A +></DT +><DT +>4-29. <A +HREF="x2180.htm#AEN2501" +>Parsing a base64 encoded part</A +></DT +><DT +>4-30. <A +HREF="x2180.htm#AEN2524" +>Parsing a quoted printable encoded part</A +></DT +><DT +>4-31. <A +HREF="x2180.htm#AEN2547" +>Parsing a binary encoded part</A +></DT +><DT +>4-32. <A +HREF="x2180.htm#AEN2580" +>Parsing a MIME encoded part</A +></DT +><DT +>4-33. <A +HREF="x2583.htm#AEN2610" +>rendering MIME header fields</A +></DT +><DT +>4-34. <A +HREF="x2583.htm#AEN2649" +>render base64 or quoted printable</A +></DT +><DT +>4-35. <A +HREF="x2669.htm#AEN2694" +>creating a MIME content disposition</A +></DT +><DT +>4-36. <A +HREF="x2669.htm#AEN2713" +>creating a MIME header fields list</A +></DT +><DT +>4-37. <A +HREF="x2669.htm#AEN2728" +>creating new fields</A +></DT +><DT +>4-38. <A +HREF="x2669.htm#AEN2746" +>Creating a MIME content type</A +></DT +><DT +>4-39. <A +HREF="x2669.htm#AEN2779" +>creating MIME content</A +></DT +><DT +>4-40. <A +HREF="x2669.htm#AEN2809" +>creating a MIME part</A +></DT +><DT +>4-41. <A +HREF="x2669.htm#AEN2837" +>setting preamble and epilogue</A +></DT +><DT +>4-42. <A +HREF="x2669.htm#AEN2861" +>creating a MIME part</A +></DT +><DT +>4-43. <A +HREF="x2669.htm#AEN2892" +>modifying MIME structure</A +></DT +><DT +>4-44. <A +HREF="x2669.htm#AEN2909" +>modifying MIME structure</A +></DT +><DT +>4-45. <A +HREF="x2669.htm#AEN2943" +>creating MIME fields with only Content-Transfer-Encoding</A +></DT +><DT +>4-46. <A +HREF="x2946.htm#AEN2960" +>extracting MIME encoding mechanism</A +></DT +><DT +>4-47. <A +HREF="x2946.htm#AEN2985" +>extracting information from MIME content type</A +></DT +><DT +>5-1. <A +HREF="x3015.htm#AEN3079" +>use of storage</A +></DT +><DT +>5-2. <A +HREF="x3082.htm#AEN3195" +>use of folder</A +></DT +><DT +>5-3. <A +HREF="x3198.htm#AEN3469" +>use of message</A +></DT +></DL +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +> </TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +> </TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="c13.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +> </TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +> </TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Introduction</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/c13.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/c13.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,139 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Introduction</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="PREVIOUS" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="NEXT" +TITLE="Tools and datatypes" +HREF="c16.htm"></HEAD +><BODY +CLASS="CHAPTER" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="book1.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +></TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="c16.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="CHAPTER" +><H1 +><A +NAME="AEN13" +></A +>Chapter 1. Introduction</H1 +><P +> This document will describe the API of libEtPan! + </P +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="c16.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>libEtPan! API</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +> </TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Tools and datatypes</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/c1586.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/c1586.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,303 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>MIME</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="PREVIOUS" +TITLE="Rendering of messages" +HREF="x1556.htm"><LINK +REL="NEXT" +TITLE="Data types" +HREF="x1614.htm"></HEAD +><BODY +CLASS="CHAPTER" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x1556.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +></TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x1614.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="CHAPTER" +><H1 +><A +NAME="AEN1586" +></A +>Chapter 4. MIME</H1 +><DIV +CLASS="TOC" +><DL +><DT +><B +>Table of Contents</B +></DT +><DT +><A +HREF="c1586.htm#AEN1598" +>Quick start</A +></DT +><DT +><A +HREF="x1614.htm" +>Data types</A +></DT +><DT +><A +HREF="x2180.htm" +>Parser functions</A +></DT +><DT +><A +HREF="x2583.htm" +>Rendering of MIME parts</A +></DT +><DT +><A +HREF="x2669.htm" +>Creation functions</A +></DT +><DT +><A +HREF="x2946.htm" +>Helper functions</A +></DT +></DL +></DIV +><P +> libEtPan! implements a MIME message parser (also known as + messages with attachments or + multipart messages). This also allows to generate MIME messages. + </P +><DIV +CLASS="WARNING" +><P +></P +><TABLE +CLASS="WARNING" +BORDER="1" +WIDTH="100%" +><TR +><TD +ALIGN="CENTER" +><B +>Warning</B +></TD +></TR +><TR +><TD +ALIGN="LEFT" +><P +> All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + </P +><P +> allocation functions will return <B +CLASS="COMMAND" +>NULL</B +> on failure + + functions returning integer will be returning one of the + following error code: + <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +>, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_PARSE</B +>, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_MEMORY</B +>, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_INVAL</B +>, + or <B +CLASS="COMMAND" +>MAILIMF_ERROR_FILE</B +>. + </P +></TD +></TR +></TABLE +></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN1598" +>Quick start</A +></H1 +><P +> You will need this module when you want to parse a MIME + message. + </P +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN1601" +>Parse MIME message</A +></H2 +><P +> You will use the following function : + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>mailmime_parse</B +> + (<A +HREF="x1094.htm#MAILIMF-ENVELOPE-AND-OPTIONAL-FIELDS-PARSE" +>the Section called <I +>mailimf_envelope_and_optional_fields_parse</I +> in Chapter 3</A +>) + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN1609" +>Render the MIME message</A +></H2 +><P +> Build your MIME message, then use + <B +CLASS="COMMAND" +>mailmime_write</B +> + (<A +HREF="x2583.htm#MAILMIME-WRITE" +>the Section called <I +>mailmime_write</I +></A +>) + to render a MIME message. + </P +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x1556.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x1614.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Rendering of messages</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +> </TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Data types</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/c16.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/c16.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,629 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Tools and datatypes</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="PREVIOUS" +TITLE="Introduction" +HREF="c13.htm"><LINK +REL="NEXT" +TITLE="List" +HREF="x88.htm"></HEAD +><BODY +CLASS="CHAPTER" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="c13.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +></TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x88.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="CHAPTER" +><H1 +><A +NAME="AEN16" +></A +>Chapter 2. Tools and datatypes</H1 +><DIV +CLASS="TOC" +><DL +><DT +><B +>Table of Contents</B +></DT +><DT +><A +HREF="c16.htm#AEN19" +>Array</A +></DT +><DT +><A +HREF="x88.htm" +>List</A +></DT +><DT +><A +HREF="x161.htm" +>Hash table</A +></DT +><DT +><A +HREF="x229.htm" +>Buffered I/O</A +></DT +><DT +><A +HREF="x289.htm" +>non-buffered I/O</A +></DT +><DT +><A +HREF="x312.htm" +>strings</A +></DT +></DL +></DIV +><P +> libEtPan! include a collection of datatypes such as lists, + arrays, hash tables and tools such as buffered I/O. + </P +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN19" +>Array</A +></H1 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +typedef struct carray_s carray; + </PRE +><P +> <B +CLASS="COMMAND" +>carray</B +> is an array of pointers that will + resize automatically in case a new element is added. + </P +><P +> + The <B +CLASS="COMMAND" +>carray</B +> is implemented with an array + <B +CLASS="COMMAND" +>(void **)</B +> that can be resized. An array has a + size: this is the number of elements that can be added before + the table is resized. It also has a count of elements: this is + the elements that exist in the array. + </P +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CARRAY-NEW" +>carray_new and carray_free</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>carray * carray_new(unsigned int initsize); + +void carray_free(carray * array); + </PRE +><P +> <B +CLASS="COMMAND" +>carray_new()</B +> creates a new array with an + initial size. The array is not resized until the number of + element reach the initial size. It returns + <B +CLASS="COMMAND" +>NULL</B +> in case of failure. + </P +><P +> <B +CLASS="COMMAND" +>carray_free()</B +> releases memory used by the + given array. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN35" +></A +><P +><B +>Example 2-1. carray creation</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <stdlib.h> + +#define SIZE 50 + +int main(void) +{ + carray * a; + + a = carray_new(SIZE); + if (a == NULL) + exit(EXIT_FAILURE); + + /* do things here */ + + carray_free(a); + + exit(EXIT_SUCESS); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CARRAY-SET-SIZE" +>carray_set_size</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int carray_set_size(carray * array, uint32_t new_size); + </PRE +><P +> <B +CLASS="COMMAND" +>carray_set_size()</B +> sets the size of the + array. It returns <B +CLASS="COMMAND" +>0</B +> in case of success, + <B +CLASS="COMMAND" +>-1</B +> in case of failure. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN45" +></A +><P +><B +>Example 2-2. preallocating carray</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <stdlib.h> + +#define SIZE 50 +#define NEWSIZE 200 + +int main(void) +{ + carray * a; + unsigned int i; + char p[500]; + + a = carray_new(SIZE); + if (a == NULL) + goto err; + + r = carray_set_size(NEWSIZE); + if (r < 0) + goto free; + + for(i = 0 ; i < NEWSIZE ; i ++) + carray_set(a, i, &p[i]); + + /* do things here */ + + carray_free(a); + + exit(EXIT_SUCESS); + + free: + carray_free(a); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CARRAY-COUNT" +>carray_count, carray_add, carray_get and carray_set</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int carray_count(carray); + +int carray_add(carray * array, void * data, unsigned int * index); + +void * carray_get(carray * array, unsigned int indx); + +void carray_set(carray * array, unsigned int indx, void * value); + </PRE +><P +> <B +CLASS="COMMAND" +>carray_count()</B +> returns the number of + elements in the <B +CLASS="COMMAND" +>carray</B +>. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>carray_add()</B +>adds an element at the end of + the array. The <B +CLASS="COMMAND" +>index</B +> of the element is + returns in <B +CLASS="COMMAND" +>(* index)</B +> if + <B +CLASS="COMMAND" +>index</B +> is not <B +CLASS="COMMAND" +>NULL</B +>. It + returns <B +CLASS="COMMAND" +>0</B +> in case of success, + <B +CLASS="COMMAND" +>-1</B +> in case of failure. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>carray_get()</B +> returns the elements contained + at the given cell of the table. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>carray_set()</B +> replace the element at the + given index of table table with the given value. + Complexity is O(1). + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN66" +></A +><P +><B +>Example 2-3. carray access</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <string.h> + +#define SIZE 50 + +int main(void) +{ + carray * a; + int r; + + a = carray_new(SIZE); + if (a == NULL) + goto err; + + r = carray_add(a, "foo-bar-1", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-2", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-3", NULL); + if (r < 0) + goto free; + + for(i = 0 ; i < carray_count(a) ; i ++) { + char * str; + + str = carray_get(a, i); + if (strcmp("foo-bar-2", str) == 0) + carray_set(a, i, "foo-bar-2-replacement"); + + printf("%s\n", str); + } + + carray_free(a); + + exit(EXIT_SUCESS); + + free: + carray_free(a); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CARRAY-DELETE" +>carray_delete</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int carray_delete(carray * array, uint32_t indx); + +int carray_delete_slow(carray * array, uint32_t indx); + +int carray_delete_fast(carray * array, uint32_t indx); + </PRE +><P +> <B +CLASS="COMMAND" +>carray_delete()</B +> removes an element of the + table. Order will not be garanteed. The returned result can + be ignored. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>carray_delete_slow()</B +> removes an element of + the table. Order will be garanteed. The returned result can + be ignored. + Complexity is O(n). + </P +><P +> <B +CLASS="COMMAND" +>carray_delete_fast()</B +> the element will just + be replaced with <B +CLASS="COMMAND" +>NULL</B +>. Order will be kept + but the number of elements will remains the same. The + returned result can be ignored. + Complexity is O(1). + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN79" +></A +><P +><B +>Example 2-4. deletion in carray</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define SIZE 50 + +carray * build_array(void) +{ + carray * a; + + a = carray_new(SIZE); + if (a == NULL) + goto err; + + r = carray_add(a, "foo-bar-1", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-2", NULL); + if (r < 0) + goto free; + + carray_add(a, "foo-bar-3", NULL); + if (r < 0) + goto free; + + return a; + + free: + carray_free(a); + err: + exit(EXIT_FAILURE); +} + +void delete(carray * a) +{ + /* deleting foo-bar-1 */ + carray_delete(a, 0); + /* resulting size is 2, order of elements is undefined */ +} + +void delete_slow(carray * a) +{ + /* deleting foo-bar-1 */ + carray_delete_slow(a, 0); + /* resulting size is 2, order of elements is the same */ +} + +void delete_fast(carray * a) +{ + /* deleting foo-bar-1 */ + carray_delete_slow(a, 0); + /* + resulting size is 3, + order of elements is { NULL, foo-bar-2, foo-bar-3 } + */ +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CARRAY-DATA" +>carray_data</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>void ** carray_data(carray); + </PRE +><P +> <B +CLASS="COMMAND" +>carray_data</B +>returns the table used for + implementation : + <B +CLASS="COMMAND" +>(void **)</B +>. + </P +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="c13.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x88.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Introduction</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +> </TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>List</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/c2988.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/c2988.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,271 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Storages, folders, messages</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="PREVIOUS" +TITLE="Helper functions" +HREF="x2946.htm"><LINK +REL="NEXT" +TITLE="Error codes" +HREF="x3011.htm"></HEAD +><BODY +CLASS="CHAPTER" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x2946.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +></TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x3011.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="CHAPTER" +><H1 +><A +NAME="AEN2988" +></A +>Chapter 5. Storages, folders, messages</H1 +><DIV +CLASS="TOC" +><DL +><DT +><B +>Table of Contents</B +></DT +><DT +><A +HREF="c2988.htm#AEN2990" +>Introduction</A +></DT +><DT +><A +HREF="x3011.htm" +>Error codes</A +></DT +><DT +><A +HREF="x3015.htm" +>Storage</A +></DT +><DT +><A +HREF="x3082.htm" +>Folder</A +></DT +><DT +><A +HREF="x3198.htm" +>Message</A +></DT +><DT +><A +HREF="x3472.htm" +>Session</A +></DT +></DL +></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN2990" +>Introduction</A +></H1 +><P +> This part will give the definition of some objects. + </P +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN2993" +>Message</A +></H2 +><P +> A message is the common e-mail message or news message you + read or send. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN2996" +>MIME part</A +></H2 +><P +> A message can have attachment such as images or other documents. + The attachment are organized into a tree structure. Each + node of this structure is a MIME part. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN2999" +>Mailbox</A +></H2 +><P +> A mailbox will contain a given number of messages. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3002" +>Storage</A +></H2 +><P +> A storage is a "physical" localisation of your mailbox. This + can be on a filesystem (local or remote disk, this is the + case of MH, mbox and maildir), or this can be on a remote + host (this is the case for POP3, IMAP or NNTP). + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3005" +>Folder</A +></H2 +><P +> A storage, for the same user, can contain a given number of + mailboxes, depending the storage capabilities, then, the + storage driver capabilities. With etPan!, MH, IMAP and NNTP + storages can have more than one mailbox. The mailboxes will + be called folders. On storage where we only have one + mailbox, the unique mailbox is the unique folder. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3008" +>Session</A +></H2 +><P +> The session is the network connection or the entity to which + the commands of the drivers are given. + </P +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x2946.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x3011.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Helper functions</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +> </TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Error codes</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/c385.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/c385.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,342 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Internet Message Format</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="PREVIOUS" +TITLE="strings" +HREF="x312.htm"><LINK +REL="NEXT" +TITLE="Data types" +HREF="x425.htm"></HEAD +><BODY +CLASS="CHAPTER" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x312.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +></TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x425.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="CHAPTER" +><H1 +><A +NAME="IMF" +></A +>Chapter 3. Internet Message Format</H1 +><DIV +CLASS="TOC" +><DL +><DT +><B +>Table of Contents</B +></DT +><DT +><A +HREF="c385.htm#AEN397" +>Quick start</A +></DT +><DT +><A +HREF="x425.htm" +>Data types</A +></DT +><DT +><A +HREF="x1094.htm" +>Parser functions</A +></DT +><DT +><A +HREF="x1381.htm" +>Creation functions</A +></DT +><DT +><A +HREF="x1556.htm" +>Rendering of messages</A +></DT +></DL +></DIV +><P +> libEtPan! implements Internet Message parser. Currently, format + is RFC 2822. + This module also allows to generate messages. + </P +><DIV +CLASS="WARNING" +><P +></P +><TABLE +CLASS="WARNING" +BORDER="1" +WIDTH="100%" +><TR +><TD +ALIGN="CENTER" +><B +>Warning</B +></TD +></TR +><TR +><TD +ALIGN="LEFT" +><P +> All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + </P +><P +> allocation functions will return <B +CLASS="COMMAND" +>NULL</B +> on failure + + functions returning integer will be returning one of the + following error code: + <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +>, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_PARSE</B +>, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_MEMORY</B +>, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_INVAL</B +>, + or <B +CLASS="COMMAND" +>MAILIMF_ERROR_FILE</B +>. + </P +></TD +></TR +></TABLE +></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN397" +>Quick start</A +></H1 +><P +> You will need this module when you want to parse headers + of messages or when you want to build message headers + conformant to standards. + </P +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN400" +>Parse message headers</A +></H2 +><P +> You will use one of the four following functions, depending + on your needs : + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>mailimf_envelope_and_optional_fields_parse</B +> + (<A +HREF="x1094.htm#MAILIMF-ENVELOPE-AND-OPTIONAL-FIELDS-PARSE" +>the Section called <I +>mailimf_envelope_and_optional_fields_parse</I +></A +>), + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mailimf_envelope_fields_parse</B +> + (<A +HREF="x1094.htm#MAILIMF-ENVELOPE-FIELDS-PARSE" +>the Section called <I +>mailimf_envelope_fields_parse</I +></A +>), + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mailimf_optional_fields_parse</B +> + (<A +HREF="x1094.htm#MAILIMF-OPTIONAL-FIELDS-PARSE" +>the Section called <I +>mailimf_optional_fields_parse</I +></A +>), + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mailimf_fields_parse</B +> + (<A +HREF="x1094.htm#MAILIMF-FIELDS-PARSE" +>the Section called <I +>mailimf_fields_parse</I +></A +>). + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN420" +>Render the message headers</A +></H2 +><P +> Build your message headers, then use + <B +CLASS="COMMAND" +>mailimf_fields_write</B +> + (<A +HREF="x1556.htm#MAILIMF-FIELDS-WRITE" +>the Section called <I +>Header fields</I +></A +>) + to render the headers. + </P +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x312.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x425.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>strings</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +> </TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Data types</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x1094.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x1094.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1683 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Parser functions</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Internet Message Format" +HREF="c385.htm"><LINK +REL="PREVIOUS" +TITLE="Data types" +HREF="x425.htm"><LINK +REL="NEXT" +TITLE="Creation functions" +HREF="x1381.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x425.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 3. Internet Message Format</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x1381.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN1094" +>Parser functions</A +></H1 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-ADDRESS-LIST-PARSE" +>mailimf_address_list_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int +mailimf_address_list_parse(char * message, size_t length, + size_t * index, + struct mailimf_address_list ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_address_list_parse()</B +> parse a list + of addresses in RFC 2822 form. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing + the list of addresses. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given string + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> this is a pointer to the + start of the list of + addresses in the given string, + <B +CLASS="COMMAND" +>(* index)</B +> is modified to point + at the end of the parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x425.htm#MAILIMF-ADDRESS-LIST" +>the Section called <I +>mailimf_address_list - list of addresses</I +></A +>). + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1120" +></A +><P +><B +>Example 3-33. parsing a list of addresses</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_address_list * addr_list; + size_t current_index; + + current_index = 0; + r = mailimf_address_list_parse(mem, stat_info.st_size, + ¤t_index, &addr_list); + if (r == MAILIMF_NO_ERROR) { + display_address_list(addr_list); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_address_list_free(addr_list); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-ADDRESS-PARSE" +>mailimf_address_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int +mailimf_address_parse(char * message, size_t length, + size_t * index, + struct mailimf_address ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_address_parse()</B +> parse an address + in RFC 2822 form. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the + address. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse operation + is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x425.htm#MAILIMF-ADDRESS" +>the Section called <I +>mailimf_address - address</I +></A +>). + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1147" +></A +><P +><B +>Example 3-34. parsing an address</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_address * addr; + size_t current_index; + + current_index = 0; + r = mailimf_address_parse(mem, stat_info.st_size, + ¤t_index, &addr); + if (r == MAILIMF_NO_ERROR) { + display_address(addr); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_address_free(addr); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-BODY-PARSE" +>mailimf_body_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailimf_body_parse(char * message, size_t length, + size_t * index, + struct mailimf_body ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_body_parse()</B +> parse text body of a + message. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing + the message body part. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> this is a pointer to the start + of the message text part in + the given string, <B +CLASS="COMMAND" +>(* index)</B +> is + modified to point at the end + of the parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x425.htm#MAILIMF-BODY" +>the Section called <I +>mailimf_body - message body without headers</I +></A +>). + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1174" +></A +><P +><B +>Example 3-35. parsing a message body</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_body * b; + struct mailimf_fields * f; + size_t current_index; + size_t size; + + size = stat_info.st_size; + current_index = 0; + r = mailimf_fields_parse(mem, size, ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + r = mailimf_crlf_parse(mem, size, ¤t_index); + /* ignore parse error of crlf */ + + r = mailimf_body_parse(mem, size, ¤t_index, &b); + if (r == MAILIMF_NO_ERROR) { + + display_body(b); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_body_free(b); + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-ENVELOPE-AND-OPTIONAL-FIELDS-PARSE" +>mailimf_envelope_and_optional_fields_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int +mailimf_envelope_and_optional_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_envelope_and_optional_fields_parse()</B +> + returns a list of most useful headers (parsed). The other + headers will be placed in the list in a non-parsed form. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the header. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given string + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the header in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end + of the parsed data + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x425.htm#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +></A +>). + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1201" +></A +><P +><B +>Example 3-36. parsing commonly used fields and return other fields + in a non-parsed form</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_envelope_and_optional_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-ENVELOPE-FIELDS-PARSE" +>mailimf_envelope_fields_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailimf_envelope_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_envelope_fields_parse()</B +> return a + list of most useful headers (parsed). + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the header + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given string + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the header in + the given string, <B +CLASS="COMMAND" +>(* index)</B +> is + modified to point at the end + of the parsed data + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x425.htm#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +></A +>). + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1228" +></A +><P +><B +>Example 3-37. parsing commonly used fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_envelope_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-OPTIONAL-FIELDS-PARSE" +>mailimf_optional_fields_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int +mailimf_optional_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_optional_fields_parse</B +> return a + list of non-parsed headers. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the header + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given string + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the header in + the given string, <B +CLASS="COMMAND" +>(* index)</B +> is + modified to point at the end + of the parsed data + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x425.htm#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +></A +>). + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1255" +></A +><P +><B +>Example 3-38. parsing optional fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_optional_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-FIELDS-PARSE" +>mailimf_fields_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailimf_fields_parse(char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_fields_parse()</B +> parse headers of a + message. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the header + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given string + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the header in + the given string, <B +CLASS="COMMAND" +>(* index)</B +> is + modified to point at the end + of the parsed data + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x425.htm#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +></A +>). + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1282" +></A +><P +><B +>Example 3-39. parsing header fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + display_fields(f); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-IGNORE-FIELD-PARSE" +>mailimf_ignore_field_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailimf_ignore_field_parse(char * message, size_t length, + size_t * index); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_ignore_field_parse()</B +> skip the + next header. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the header + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given string + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the field to skip in + the given string, <B +CLASS="COMMAND" +>(* index)</B +> is + modified to point at the end + of the parsed data + </P +></LI +></UL +><P +> return <B +CLASS="COMMAND" +>MAILIMF_NO_ERROR</B +> on success, + <B +CLASS="COMMAND" +>MAILIMF_ERROR_XXX</B +> on error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1304" +></A +><P +><B +>Example 3-40. skipping fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + size_t current_index; + + current_index = 0; + r = mailimf_ignore_field_parse(mem, stat_info.st_size, + ¤t_index); + if (r == MAILIMF_NO_ERROR) { + /* do the things */ + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-MAILBOX-LIST-PARSE" +>mailimf_mailbox_list_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int +mailimf_mailbox_list_parse(char * message, size_t length, + size_t * index, + struct mailimf_mailbox_list ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_list_parse()</B +> parse a list + of mailboxes in RFC 2822 form. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the + list of mailboxes. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the list of + mailboxes in the given string, + <B +CLASS="COMMAND" +>(* index)</B +> is modified to point + at the end of the parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +>. + (see <A +HREF="x425.htm#MAILIMF-MAILBOX-LIST" +>the Section called <I +>mailimf_mailbox_list - list of mailboxes</I +></A +>) + </P +></LI +></UL +><P +> return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on + error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1329" +></A +><P +><B +>Example 3-41. parsing a list of mailboxes</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_mailbox_list * mb_list; + size_t current_index; + + current_index = 0; + r = mailimf_mailbox_list_parse(mem, stat_info.st_size, + ¤t_index, &mb_list); + if (r == MAILIMF_NO_ERROR) { + display_mailbox_list(mb_list); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_mailbox_list_free(mb_list); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-MAILBOX-PARSE" +>mailimf_mailbox_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +> +#include <libetpan/libetpan.h> + +int mailimf_mailbox_parse(char * message, size_t length, + size_t * index, + struct mailimf_mailbox ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_parse</B +> parse a mailbox in + RFC 2822 form. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing the + mailbox. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> this is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> index this is a pointer to the + start of the mailbox in the given string, + <B +CLASS="COMMAND" +>(* index)</B +> is modified to point + at the end of the parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +> the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +>. + (see <A +HREF="x425.htm#MAILIMF-MAILBOX" +>the Section called <I +>mailimf_mailbox - mailbox</I +></A +>) + </P +></LI +></UL +><P +> return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on + error. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1354" +></A +><P +><B +>Example 3-42. parsing a mailbox</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_mailbox_list * mb_list; + size_t current_index; + + current_index = 0; + r = mailimf_mailbox_parse(mem, stat_info.st_size, + ¤t_index, &mb_list); + if (r == MAILIMF_NO_ERROR) { + display_mailbox_list(mb_list); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_mailbox_free(mb_list); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-MESSAGE-PARSE" +>mailimf_message_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailimf_message_parse(char * message, size_t length, + size_t * index, + struct mailimf_message ** result); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_message_parse</B +> parse message + (headers and body). + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> this is a string containing + the message content. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>param</B +> length this is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>param</B +> index this is a pointer to the + start of the message in + the given string, <B +CLASS="COMMAND" +>(* index)</B +> is + modified to point at the end + of the parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>param</B +> result the result of the parse + operation is stored in + <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x425.htm#MAILIMF-MESSAGE" +>the Section called <I +>mailimf_message - parsed message</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1378" +></A +><P +><B +>Example 3-43. parsing a message</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_message * m; + size_t current_index; + + current_index = 0; + r = mailimf_message_parse(mem, stat_info.st_size, + ¤t_index, &m); + if (r == MAILIMF_NO_ERROR) { + display_message(m); + /* do the things */ + status = EXIT_SUCCESS; + mailimf_message_free(m); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x425.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x1381.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Data types</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c385.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Creation functions</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x1381.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x1381.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,955 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Creation functions</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Internet Message Format" +HREF="c385.htm"><LINK +REL="PREVIOUS" +TITLE="Parser functions" +HREF="x1094.htm"><LINK +REL="NEXT" +TITLE="Rendering of messages" +HREF="x1556.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x1094.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 3. Internet Message Format</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x1556.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN1381" +>Creation functions</A +></H1 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-MAILBOX-LIST-ADD" +>mailimf_mailbox_list</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new_empty(); + +int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list, + struct mailimf_mailbox * mb); + +int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list, + char * mb_str); + +int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list, + char * display_name, char * address); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_list_new_empty()</B +> creates a + new empty list of mailboxes. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_list_add</B +> adds a mailbox + to the list of mailboxes. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_list_add_parse</B +> adds a + mailbox given in form of a string to the list of mailboxes. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_list_add_mb</B +> adds a + mailbox given in form of a couple : display name, mailbox + address. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>mailbox_list</B +> is the list of mailboxes. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mb</B +> is a mailbox + (see <A +HREF="x425.htm#MAILIMF-MAILBOX" +>the Section called <I +>mailimf_mailbox - mailbox</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mb_str</B +> is a mailbox given in the form + of a string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>display_name</B +> is the display name. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>address</B +> is the mailbox address. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1411" +></A +><P +><B +>Example 3-44. creating a list of mailboxes</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_mailbox * mb; + + mb_list = mailimf_mailbox_list_new_empty(); + + mb = mailimf_mailbox_new(strdup("DINH Viet Hoa"), + strdup("dinh.viet.hoa@free.fr")); + mailimf_mailbox_list_add(mb_list, mb); + + mailimf_mailbox_list_add_parse(mb_list, "foo bar <foo@bar.org>"); + + mailimf_mailbox_list_add_mb(mb_list, strdup("bar foo"), strdup("bar@foo.com")); + + mailimf_mailbox_list_free(mb_list); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-ADDRESS-LIST-ADD" +>mailimf_address_list</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_address_list * mailimf_address_list_new_empty(); + +int mailimf_address_list_add(struct mailimf_address_list * address_list, + struct mailimf_address * addr); + +int mailimf_address_list_add_parse(struct mailimf_address_list * address_list, + char * addr_str); + +int mailimf_address_list_add_mb(struct mailimf_address_list * address_list, + char * display_name, char * address); + </PRE +><P +> <B +CLASS="COMMAND" +>mailimf_address_list_new_empty()</B +> creates a + new empty list of addresses. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_address_list_add</B +> adds an address + to the list of addresses. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_address_list_add_parse</B +> adds an + address given in form of a string to the list of addresses. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_address_list_add_mb</B +> adds a + mailbox given in form of a couple : display name, mailbox + address. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>address_list</B +> is the list of mailboxes. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>addr</B +> is an address. + (see <A +HREF="x425.htm#MAILIMF-ADDRESS" +>the Section called <I +>mailimf_address - address</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>addr_str</B +> is an address given in the form of a + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>display_name</B +> is the display name. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>address</B +> is the mailbox address. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-FIELDS-ADD" +>mailimf_fields</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_fields * +mailimf_fields_new_empty(void); + +struct mailimf_field * mailimf_field_new_custom(char * name, char * value); + +int mailimf_fields_add(struct mailimf_fields * fields, + struct mailimf_field * field); + +int mailimf_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * msg_id, + clist * in_reply_to, + clist * references, + char * subject); + +struct mailimf_fields * +mailimf_fields_new_with_data_all(struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * message_id, + clist * in_reply_to, + clist * references, + char * subject); + +struct mailimf_fields * +mailimf_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + clist * in_reply_to, + clist * references, + char * subject); + +char * mailimf_get_message_id(void); + +struct mailimf_date_time * mailimf_get_current_date(void); + +int +mailimf_resent_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * resent_date, + struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +struct mailimf_fields * +mailimf_resent_fields_new_with_data_all(struct mailimf_date_time * + resent_date, struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +struct mailimf_fields * +mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc); + </PRE +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>from</B +> is the parsed content of the + From field + (see <A +HREF="x425.htm#MAILIMF-FROM" +>the Section called <I +>mailimf_from - parsed content of From header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sender</B +> is the parsed content of the + Sender field + (see <A +HREF="x425.htm#MAILIMF-SENDER" +>the Section called <I +>mailimf_sender - parsed content of Sender header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>reply_to</B +> is the parsed content of the + <B +CLASS="COMMAND" +>Reply-To</B +> field + (see <A +HREF="x425.htm#MAILIMF-REPLY-TO" +>the Section called <I +>mailimf_reply_to - parsed content of Reply-To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>to</B +> is the parsed content of the + <B +CLASS="COMMAND" +>To</B +> field + (see <A +HREF="x425.htm#MAILIMF-TO" +>the Section called <I +>mailimf_to - parsed content of To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>cc</B +> is the parsed content of the + <B +CLASS="COMMAND" +>Cc</B +> field + (see <A +HREF="x425.htm#MAILIMF-CC" +>the Section called <I +>mailimf_cc - parsed content of Cc</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>bcc</B +> is the parsed content of the + <B +CLASS="COMMAND" +>Bcc</B +> field + (see <A +HREF="x425.htm#MAILIMF-BCC" +>the Section called <I +>mailimf_bcc - parsed content of Bcc field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>message_id</B +> is the parsed content of + the <B +CLASS="COMMAND" +>Message-ID</B +> field + (see <A +HREF="x425.htm#MAILIMF-MESSAGE-ID" +>the Section called <I +>mailimf_message_id - parsed content of Message-ID header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>in_reply_to</B +> is the parsed content of + the <B +CLASS="COMMAND" +>In-Reply-To</B +> field + (see <A +HREF="x425.htm#MAILIMF-IN-REPLY-TO" +>the Section called <I +>mailimf_in_reply_to - parsed content of In-Reply-To + field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>references</B +> is the parsed content of + the <B +CLASS="COMMAND" +>References</B +> field + (see <A +HREF="x425.htm#MAILIMF-REFERENCES" +>the Section called <I +>mailimf_references - parsed content of References field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>subject</B +> is the content of the + <B +CLASS="COMMAND" +>Subject</B +> field + (see <A +HREF="x425.htm#MAILIMF-SUBJECT" +>the Section called <I +>mailimf_subject - parsed content of Subject field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>resent_date</B +> is the parsed content of + the <B +CLASS="COMMAND" +>Resent-Date</B +> field + (see <A +HREF="x425.htm#MAILIMF-ORIG-DATE" +>the Section called <I +>mailimf_orig_date - parsed content of date header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>resent_from</B +> is the parsed content of + the <B +CLASS="COMMAND" +>Resent-From</B +> field + (see <A +HREF="x425.htm#MAILIMF-FROM" +>the Section called <I +>mailimf_from - parsed content of From header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>resent_sender</B +> is the parsed content of the + <B +CLASS="COMMAND" +>Resent-Sender</B +> field + (see <A +HREF="x425.htm#MAILIMF-SENDER" +>the Section called <I +>mailimf_sender - parsed content of Sender header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>resent_to</B +> is the parsed content of + the <B +CLASS="COMMAND" +>Resent-To</B +> field + (see <A +HREF="x425.htm#MAILIMF-TO" +>the Section called <I +>mailimf_to - parsed content of To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>resent_cc</B +> is the parsed content of + the <B +CLASS="COMMAND" +>Resent-Cc</B +> field + (see <A +HREF="x425.htm#MAILIMF-CC" +>the Section called <I +>mailimf_cc - parsed content of Cc</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>resent_bcc</B +> is the parsed content of the + <B +CLASS="COMMAND" +>Resent-Bcc</B +> field + (see <A +HREF="x425.htm#MAILIMF-BCC" +>the Section called <I +>mailimf_bcc - parsed content of Bcc field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>resent_msg_id</B +> is the parsed content of the + <B +CLASS="COMMAND" +>Resent-Message-ID</B +> field + (see <A +HREF="x425.htm#MAILIMF-MESSAGE-ID" +>the Section called <I +>mailimf_message_id - parsed content of Message-ID header</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_fields_new_empty()</B +> creates a new + empty set of headers. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_field_new_custom()</B +> creates a new + custom header. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_fields_add()</B +> adds a header to the + set of headers. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_fields_add_data()</B +> adds some headers + to the set of headers. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_fields_new_with_data_all()</B +> creates + a set of headers with some headers (including Date and + Message-ID). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_fields_new_with_data()</B +> creates a + set of headers with some headers (Date and Message-ID will + be generated). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_get_message_id()</B +> generates a + Message-ID. The result must be freed using + <B +CLASS="COMMAND" +>free()</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_get_current_date()</B +> generates a + Date. The result must be freed using + <B +CLASS="COMMAND" +>mailimf_date_time_free</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_resent_fields_add_data()</B +> adds some + resent headers to the set of headers. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_resent_fields_new_with_data_all()</B +> + creates a set of headers with some resent headers (including + Resent-Date and Resent-Message-ID). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_resent_fields_new_with_data()</B +> + creates a set of headers with some resent headers + (Resent-Date and Resent-Message-ID will be generated) + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1553" +></A +><P +><B +>Example 3-45. creation of header fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_field * field; + struct mailimf_date_time * date; + char * msg_id; + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + + fields = mailimf_fields_new_empty(); + field = mailimf_field_new_custom(strdup("X-Mailer"), strdup("my-mailer")); + mailimf_fields_add(fields, field); + + from = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet.hoa@free.fr"); + date = mailimf_get_current_date(); + msg_id = mailimf_get_message_id(); + to = mailimf_address_list_new_empty(); + mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org"); + + mailimf_fields_add_data(fields, date, from, NULL, NULL, to, NULL, NULL, + msg_id, NULL, NULL, strdup("hello")); + + /* do the things */ + + mailimf_fields_free(fields); +} + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + struct mailimf_date_time * date; + char * msg_id; + + from = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet.hoa@free.fr"); + to = mailimf_address_list_new_empty(); + mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org"); + date = mailimf_get_current_date(); + msg_id = mailimf_get_message_id(); + + fields = mailimf_fields_new_with_all_data(date, from, NULL, NULL, to, NULL, NULL, + msg_id, NULL, NULL, strdup("hello")); + + /* do the things */ + + mailimf_fields_free(fields); +} + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + + from = mailimf_mailbox_list_new_empty(); + mailimf_mailbox_list_add_mb(from, strdup("DINH Viet Hoa"), strdup("dinh.viet.hoa@free.fr"); + to = mailimf_address_list_new_empty(); + mailimf_address_list_add_mb(to, strdup("FOO Bar"), strdup("foo@bar.org"); + + fields = mailimf_fields_new_with_data(from, NULL, NULL, to, NULL, NULL, + NULL, NULL, strdup("hello")); + + /* do the things */ + + mailimf_fields_free(fields); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x1094.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x1556.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Parser functions</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c385.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Rendering of messages</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x1556.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x1556.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,295 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Rendering of messages</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Internet Message Format" +HREF="c385.htm"><LINK +REL="PREVIOUS" +TITLE="Creation functions" +HREF="x1381.htm"><LINK +REL="NEXT" +TITLE="MIME" +HREF="c1586.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x1381.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 3. Internet Message Format</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="c1586.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN1556" +>Rendering of messages</A +></H1 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-FIELDS-WRITE" +>Header fields</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field); + </PRE +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>col</B +> current column is given for wrapping + purpose in <B +CLASS="COMMAND" +>(* col)</B +>, + the resulting columns will be returned.. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>f</B +> is the file descriptor. It can be + stdout for example. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fields</B +> is the header fields + (see <A +HREF="x425.htm#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>field</B +> is a field + (see <A +HREF="x425.htm#MAILIMF-FIELD" +>the Section called <I +>mailimf_field - header field</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_fields_write</B +> outputs the set of + header fields. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_envelope_fields_write</B +> outputs the + set of header fields except the optional fields. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_field_write</B +> outputs a header. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1583" +></A +><P +><B +>Example 3-46. rendering of fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + int col; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_imf_fields(); + + col = 0; + mailimf_fields_write(stdout, &col, fields); + + mailimf_fields_free(fields); +} + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + int col; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_imf_fields(); + + col = 0; + mailimf_envelope_fields_write(stdout, &col, fields); + + mailimf_fields_free(fields); +} + +int main(int argc, char ** argv) +{ + struct mailimf_field * field; + int col; + + field = mailimf_field_new_custom(strdup("X-Mailer"), strdup("my mailer")); + + col = 0; + mailimf_field_write(stdout, &col, field); + + mailimf_field_free(field); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x1381.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="c1586.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Creation functions</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c385.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>MIME</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x161.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x161.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,557 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Hash table</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Tools and datatypes" +HREF="c16.htm"><LINK +REL="PREVIOUS" +TITLE="List" +HREF="x88.htm"><LINK +REL="NEXT" +TITLE="Buffered I/O" +HREF="x229.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x88.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 2. Tools and datatypes</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x229.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN161" +>Hash table</A +></H1 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +typedef struct chash chash; + +typedef struct chashcell chashiter; + +typedef struct { + char * data; + int len; +} chashdatum; + </PRE +><P +> + <B +CLASS="COMMAND" +>chash</B +> is a hash table. + <B +CLASS="COMMAND" +>chashiter</B +> is a pointer to an element of the + hash table. + <B +CLASS="COMMAND" +>chashdatum</B +> is an element to be placed in + the hash table as a key or a value. It consists in + data and a corresponding length. + </P +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CHASH-NEW" +>chash_new and chash_free</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#define CHASH_COPYNONE 0 +#define CHASH_COPYKEY 1 +#define CHASH_COPYVALUE 2 +#define CHASH_COPYALL (CHASH_COPYKEY | CHASH_COPYVALUE) + +chash * chash_new(int size, int flags); + +void chash_free(chash * hash); + </PRE +><P +> <B +CLASS="COMMAND" +>chash_new()</B +> returns a new empty hash table + or <B +CLASS="COMMAND" +>NULL</B +> if this + failed. <B +CLASS="COMMAND" +>size</B +> is the initial size of the + table used for implementation. <B +CLASS="COMMAND" +>flags</B +> can + be a combinaison of <B +CLASS="COMMAND" +>CHASH_COPYKEY</B +> and + <B +CLASS="COMMAND" +>CHASH_COPYVALUE</B +>. + <B +CLASS="COMMAND" +>CHASH_COPYKEY</B +> enables copy of key, so + that the initial value used for <B +CLASS="COMMAND" +>chash_set()</B +> + </P +><P +> <B +CLASS="COMMAND" +>chash_free()</B +> releases memory used by the + hash table. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CHASH-GET" +>chash_set and chash_get</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int chash_set(chash * hash, + chashdatum * key, chashdatum * value, chashdatum * oldvalue); + +int chash_get(chash * hash, + chashdatum * key, chashdatum * result); + </PRE +><P +> <B +CLASS="COMMAND" +>chash_set()</B +> adds a new element into the + hash table. If a previous element had the same key, it is + returns into oldvalue if <B +CLASS="COMMAND" +>oldvalue</B +> is + different of NULL. + Medium complexity is O(1). + </P +><P +> returns -1 if it fails, 0 on success. + </P +><P +> <B +CLASS="COMMAND" +>chash_get()</B +>returns the corresponding value + of the given key. If there is no corresponding value, -1 is + returned. 0 on success. + Medium complexity is O(1). + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN191" +></A +><P +><B +>Example 2-9. chash insert and lookup</B +></P +><PRE +CLASS="PROGRAMLISTING" +>int main(void) +{ + chash * hash; + int r; + chashdatum key; + chashdatum value; + char * str1 = "my-data"; + char * str2 = "my-data"; + + hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE); + + key.data = "foo"; + key.len = strlen("foo"); + value.data = str1; + value.data = strlen(str1) + 1; + /* + 1 is needed to get the terminal zero in the returned string */ + r = chash_set(hash, &key, &value, NULL); + if (r < 0) + goto free_hash; + + key.data = "bar"; + key.len = strlen("bar"); + value.data = str2; + value.data = strlen(str2) + 1; + if (r < 0) + goto free_hash; + + key.data = "foo"; + key.len = strlen("foo"); + r = chash_get(hash, &key, &value); + if (r < 0) { + printf("element not found\n"); + } + else { + char * str; + + str = value.data; + printf("found : %s", str); + } + + chash_free(hash); + + exit(EXIT_SUCCESS); + + free_hash: + chash_free(hash); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CHASH-DELETE" +>chash_delete</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int chash_delete(chash * hash, + chashdatum * key, chashdatum * oldvalue); + </PRE +><P +> deletes the key/value pair given the corresponding key. + The value is returned in old_value. + If there is no corresponding value, -1 is returned. 0 on success. + Medium complexity is O(1). + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN198" +></A +><P +><B +>Example 2-10. key deletion in a chash</B +></P +><PRE +CLASS="PROGRAMLISTING" +>int main(void) +{ + chash * hash; + int r; + chashdatum key; + chashdatum value; + char * str1 = "my-data"; + char * str2 = "my-data"; + + hash = build_hash(); + + key.data = "foo"; + key.len = strlen("foo"); + chash_delete(hash, &key, &value); + + /* it will never be possible to lookup "foo" */ + key.data = "foo"; + key.len = strlen("foo"); + r = chash_get(hash, &key, &value); + if (r < 0) { + printf("element not found\n"); + } + else { + char * str; + + str = value.data; + printf("found : %s", str); + } + + chash_free(hash); + + exit(EXIT_SUCCESS); + + free_hash: + chash_free(hash); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CHASH-RESIZE" +>chash_resize</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int chash_resize(chash * hash, int size); + </PRE +><P +> <B +CLASS="COMMAND" +>chash_resize()</B +> changes the size of the + table used for implementation of the hash table. + returns 0 on success, -1 on failure. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CHASH-BEGIN" +>running through the chash</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>chashiter * chash_begin(chash * hash); + +chashiter * chash_next(chash * hash, chashiter * iter); + +void chash_key(chashiter * iter, chashdatum * result); + +void chash_value(chashiter iter, chashdatum * result); + </PRE +><P +> <B +CLASS="COMMAND" +>chash_begin()</B +> returns a pointer to the + first element of the hash table. Returns + <B +CLASS="COMMAND" +>NULL</B +> if there is no elements in the hash + table. + Complexity is O(n). + </P +><P +> <B +CLASS="COMMAND" +>chash_next()</B +> returns a pointer to the next + element of the hash table. Returns <B +CLASS="COMMAND" +>NULL</B +> + if there is no next element. + Complexity is O(n) but n calls to chash_next() also has + a complexity of O(n). + </P +><P +> <B +CLASS="COMMAND" +>chash_key()</B +> returns the key of the given + element of the hash table. + </P +><P +> <B +CLASS="COMMAND" +>chash_value</B +> returns the value of the + given element of the hash table. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN219" +></A +><P +><B +>Example 2-11. running through a chash</B +></P +><PRE +CLASS="PROGRAMLISTING" +>int main(void) +{ + chash * hash; + int r; + chashiter * iter; + + hash = build_hash(); + + /* this will display all the values stored in the hash */ + for(iter = chash_begin(hash) ; iter != NULL ; iter = + chash_next(hash, iter)) { + chashdatum key; + chashdatum value; + char * str; + + chash_value(iter, &value); + str = value.data; + printf("%s\n", str); + } + + chash_free(hash); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CHASH-COUNT" +>chash_size and chash_count</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int chash_size(chash * hash); + +int chash_count(chash * hash); + </PRE +><P +> <B +CLASS="COMMAND" +>chash_size()</B +> returns the size of the table + used for implementation of the hash table. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>chash_count()</B +> returns the number of + elements in the hash table. + Complexity is O(1). + </P +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x88.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x229.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>List</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c16.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Buffered I/O</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x1614.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x1614.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3534 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Data types</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="MIME" +HREF="c1586.htm"><LINK +REL="PREVIOUS" +TITLE="MIME" +HREF="c1586.htm"><LINK +REL="NEXT" +TITLE="Parser functions" +HREF="x2180.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="c1586.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 4. MIME</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x2180.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN1614" +>Data types</A +></H1 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-COMPOSITE-TYPE" +>mailmime_composite_type - Composite MIME type</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_COMPOSITE_TYPE_ERROR, + MAILMIME_COMPOSITE_TYPE_MESSAGE, + MAILMIME_COMPOSITE_TYPE_MULTIPART, + MAILMIME_COMPOSITE_TYPE_EXTENSION +}; + +struct mailmime_composite_type { + int ct_type; + char * ct_token; +}; + +struct mailmime_composite_type * +mailmime_composite_type_new(int ct_type, char * ct_token); + +void mailmime_composite_type_free(struct mailmime_composite_type * ct); + </PRE +><P +> This is a MIME composite type such as <B +CLASS="COMMAND" +>message</B +> or + <B +CLASS="COMMAND" +>multipart</B +>. + </P +><P +> <B +CLASS="COMMAND" +>ct_type</B +> can have one of the 3 following values : + <B +CLASS="COMMAND" +>MAILMIME_COMPOSITE_TYPE_MESSAGE</B +> when the + composite MIME type + is <B +CLASS="COMMAND" +>message</B +>, + <B +CLASS="COMMAND" +>MAILMIME_COMPOSITE_TYPE_MULTIPART</B +> when + the composite MIME type + is <B +CLASS="COMMAND" +> multipart</B +>, + <B +CLASS="COMMAND" +>MAILMIME_COMPOSITE_TYPE_EXTENSION</B +> for + other and <B +CLASS="COMMAND" +>ct_token</B +> is set + in this case. + <B +CLASS="COMMAND" +>MAILMIME_COMPOSITE_TYPE_ERROR</B +> is used + internally on parse error. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_composite_type_new()</B +> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_composite_type_free()</B +> frees + memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1635" +></A +><P +><B +>Example 4-1. create and display MIME composite type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(void) +{ + struct mailmime_composite_type * ct; + + ct = mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL); + + /* do your things ... */ + + mailmime_composite_type_free(ct); + + exit(EXIT_SUCCESS); +} + +void display_composite_type() +{ + switch (ct->type) { + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + printf("composite type is message\n"); + break; + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + printf("composite type is multipart\n"); + break; + case MAILMIME_COMPOSITE_TYPE_EXTENSION: + printf("composite type: %s\n", ct->ct_token); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-CONTENT" +>mailmime_content - MIME content type (Content-Type)</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_content { + struct mailmime_type * ct_type; + char * ct_subtype; + clist * ct_parameters; /* elements are (struct mailmime_parameter *) */ +}; + +struct mailmime_content * +mailmime_content_new(struct mailmime_type * ct_type, + char * ct_subtype, + clist * ct_parameters); + +void mailmime_content_free(struct mailmime_content * content); + </PRE +><P +> This is a MIME content type such as <B +CLASS="COMMAND" +>message/rfc822</B +> or + <B +CLASS="COMMAND" +>text/plain</B +>. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>ct_type</B +> is the main MIME type, + for example <B +CLASS="COMMAND" +>text</B +> in + <B +CLASS="COMMAND" +>plain/text</B +> + (see <A +HREF="x1614.htm#MAILMIME-TYPE" +>the Section called <I +>mailmime_type - MIME main type</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>ct_subtype</B +> is the MIME subtype, + for example <B +CLASS="COMMAND" +>plain</B +> in + <B +CLASS="COMMAND" +>plain/text</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>ct_parameters</B +> is the list of parameters for + the given MIME type. For example, for <B +CLASS="COMMAND" +>plain/text</B +>, + we can find <B +CLASS="COMMAND" +>charset=iso-8859-1</B +>, + <B +CLASS="COMMAND" +>format=flowed</B +>. Each element of the list + if of type <B +CLASS="COMMAND" +>struct mailmime_parameter *</B +> + (see <A +HREF="x1614.htm#MAILMIME-PARAMETER" +>the Section called <I +>mailmime_parameter - MIME type parameter</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailmime_content_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_content_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1667" +></A +><P +><B +>Example 4-2. Creation and display of MIME content type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(void) +{ + struct mailmime_content * content; + struct mailmime_type * type; + struct mailmime_discrete_type * dt; + struct mailmime_parameter * param; + clist * param_list; + + dt = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, NULL); + type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, dt, NUL); + param_list = clist_new(); + param = mailmime_parameter_new(strdup("charset"), strdup("iso-8859-1")); + clist_append(param_list, param); + + content = mailmime_content_new(type, strdup("plain"), param_list); + + /* do your things */ + + exit(EXIT_SUCCESS); +} + +void display_mime_content(struct mailmime_content * content_type) +{ + clistiter * cur; + + printf("type:\n"); + display_type(content_type->ct_type); + printf("\n"); + printf("subtype: %s\n", content_type->ct_subtype); + printf("\n"); + + for(cur = clist_begin(content_type->ct_parameters) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + display_mime_parameter(param); + printf("\n"); + } + printf("\n"); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-DISCRETE-TYPE" +>mailmime_discrete_type - MIME discrete type</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISCRETE_TYPE_ERROR, + MAILMIME_DISCRETE_TYPE_TEXT, + MAILMIME_DISCRETE_TYPE_IMAGE, + MAILMIME_DISCRETE_TYPE_AUDIO, + MAILMIME_DISCRETE_TYPE_VIDEO, + MAILMIME_DISCRETE_TYPE_APPLICATION, + MAILMIME_DISCRETE_TYPE_EXTENSION +}; + +struct mailmime_discrete_type { + int dt_type; + char * dt_extension; +}; + +struct mailmime_discrete_type * +mailmime_discrete_type_new(int dt_type, char * dt_extension); + +void mailmime_discrete_type_free(struct mailmime_discrete_type * + discrete_type); + </PRE +><P +> This is a MIME discrete type such as <B +CLASS="COMMAND" +>text</B +> or + <B +CLASS="COMMAND" +>image</B +>. This is also known as single part. This kind + of part does not have any child. + </P +><P +> <B +CLASS="COMMAND" +>dt_type</B +> is one of the given values : + <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_TEXT</B +> if part is text, + <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_IMAGE</B +> if part is an image, + <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_AUDIO</B +> if part is + audio data, + <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_VIDEO</B +> if part is video, + <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_APPLICATION</B +> if + part is application data or + <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_EXTENSION</B +> for other. + In the case of <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_EXTENSION</B +>, + <B +CLASS="COMMAND" +>dt_extension</B +> is filled in. + <B +CLASS="COMMAND" +>MAILMIME_DISCRETE_TYPE_ERROR</B +> is used internally. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_discrete_type_new()</B +> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_discrete_type_free()</B +> frees + memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1691" +></A +><P +><B +>Example 4-3. Creation and display of MIME discrete type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +/* standard type */ + +int main(int argc, char ** argv) +{ + struct mailmime_discrete_type * discrete_type; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, + NULL); + + /* do the things */ + + mailmime_discrete_type_free(discrete_type); +} + +/* extension */ + +int main(int argc, char ** argv) +{ + struct mailmime_discrete_type * discrete_type; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_EXTENSION, + strdup("my-type")); + + /* do the things */ + + mailmime_discrete_type_free(discrete_type); +} + +void display_mime_discrete_type(struct mailmime_discrete_type * discrete_type) +{ + switch (discrete_type->dt_type) { + case MAILMIME_DISCRETE_TYPE_TEXT: + printf("text\n"); + break; + case MAILMIME_DISCRETE_TYPE_IMAGE: + printf("image\n"); + break; + case MAILMIME_DISCRETE_TYPE_AUDIO: + printf("audio\n"); + break; + case MAILMIME_DISCRETE_TYPE_VIDEO: + printf("video\n"); + break; + case MAILMIME_DISCRETE_TYPE_APPLICATION: + printf("application\n"); + break; + case MAILMIME_DISCRETE_TYPE_EXTENSION: + printf("extension : %s\n", discrete_type->dt_extension); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELD" +>mailmime_field - MIME header field</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_FIELD_NONE, + MAILMIME_FIELD_TYPE, + MAILMIME_FIELD_TRANSFER_ENCODING, + MAILMIME_FIELD_ID, + MAILMIME_FIELD_DESCRIPTION, + MAILMIME_FIELD_VERSION, + MAILMIME_FIELD_DISPOSITION, + MAILMIME_FIELD_LANGUAGE, +}; + +struct mailmime_field { + int fld_type; + union { + struct mailmime_content * fld_content; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + struct mailmime_language * fld_language; + } fld_data; +}; + +struct mailmime_field * +mailmime_field_new(int fld_type, + struct mailmime_content * fld_content, + struct mailmime_mechanism * fld_encoding, + char * fld_id, + char * fld_description, + uint32_t fld_version, + struct mailmime_disposition * fld_disposition, + struct mailmime_language * fld_language); + +void mailmime_field_free(struct mailmime_field * field); + </PRE +><P +> This is a parsed MIME header field; + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fld_type</B +> is the type of MIME header field. The value can + be + <B +CLASS="COMMAND" +>MAILMIME_FIELD_TYPE</B +> + if field is <B +CLASS="COMMAND" +>Content-Type</B +>, + <B +CLASS="COMMAND" +>MAILMIME_FIELD_TRANSFER_ENCODING</B +> + if field is <B +CLASS="COMMAND" +>Content-Transfer-Encoding</B +>, + <B +CLASS="COMMAND" +>MAILMIME_FIELD_ID</B +> + if field is <B +CLASS="COMMAND" +>Content-ID</B +>, + <B +CLASS="COMMAND" +>MAILMIME_FIELD_DESCRIPTION</B +> + if field is <B +CLASS="COMMAND" +>Content-Description</B +>, + <B +CLASS="COMMAND" +>MAILMIME_FIELD_VERSION</B +> + if field is <B +CLASS="COMMAND" +>MIME-Version</B +>, + <B +CLASS="COMMAND" +>MAILMIME_FIELD_DISPOSITION</B +> + if field is <B +CLASS="COMMAND" +>Content-Disposition</B +> or + <B +CLASS="COMMAND" +>MAILMIME_FIELD_LANGUAGE</B +> + if field is <B +CLASS="COMMAND" +>Content-Language</B +>. + <B +CLASS="COMMAND" +>MAILMIME_FIELD_NONE</B +> is used internally. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_content</B +> is set in case of + <B +CLASS="COMMAND" +>Content-Type</B +>. + (see <A +HREF="x1614.htm#MAILMIME-CONTENT" +>the Section called <I +>mailmime_content - MIME content type (Content-Type)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_encoding</B +> is set in case of + <B +CLASS="COMMAND" +>Content-Transfer-Encoding</B +>. + (see <A +HREF="x1614.htm#MAILMIME-MECHANISM" +>the Section called <I +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_id</B +> is set in case of + <B +CLASS="COMMAND" +>Content-ID</B +>. This is a string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_description</B +> is set in case of + <B +CLASS="COMMAND" +>Content-Description</B +>. This is a string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_version</B +> is set in case of + <B +CLASS="COMMAND" +>MIME-Version</B +>. This is an integer built + using the following formula : + <B +CLASS="COMMAND" +>fld_version = major * 2^16 + minor</B +>. + Currenly MIME-Version is always <B +CLASS="COMMAND" +>1.0</B +>, this means that + fld_version will always be <B +CLASS="COMMAND" +>2^16</B +> (in C language, + this is <B +CLASS="COMMAND" +>1 << 16</B +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_disposition</B +> is set in case of + <B +CLASS="COMMAND" +>Content-Disposition</B +>. + (see <A +HREF="x1614.htm#MAILMIME-DISPOSITION" +>the Section called <I +>mailmime_disposition - MIME disposition information (Content-Disposition)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_language</B +> is set in case of + <B +CLASS="COMMAND" +>Content-Language</B +>. + (see <A +HREF="x1614.htm#MAILMIME-LANGUAGE" +>the Section called <I +>mailmime_language - Language of MIME part</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailmime_field_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_field_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1757" +></A +><P +><B +>Example 4-4. Creation and display of MIME header field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_field * field; + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL); + + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, encoding, NULL, NULL, 0, NULL, NULL); + + /* do the things */ + + mailmime_field_free(field); +} + +void display_mime_field(struct mailmime_field * field) +{ + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + printf("content-type:"); + display_mime_content(field->fld_data.fld_content); + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + printf("content-transfer-encoding:"); + display_mime_mechanism(field->fld_data.fld_encoding); + break; + case MAILMIME_FIELD_ID: + printf("content-id: %s\n", field->fld_data.fld_id); + break; + case MAILMIME_FIELD_DESCRIPTION: + printf("content-description: %s\n", field->fld_data.fld_description); + break; + case MAILMIME_FIELD_VERSION: + printf("mime-version: %i.%i\n", + field->version>> 16, field->fld_data.fld_version & 0xFFFF); + break; + case MAILMIME_FIELD_DISPOSITION: + printf("content-disposition:"); + display_mime_disposition(field->fld_data.fld_disposition); + break; + case MAILMIME_FIELD_LANGUAGE: + printf("content-language:"); + display_mime_language(field->fld_data.fld_language); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-MECHANISM" +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_mechanism { + int enc_type; + char * enc_token; +}; + +struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token); + +void mailmime_mechanism_free(struct mailmime_mechanism * mechanism); + </PRE +><P +> This is a MIME transfer encoding mechanism description. + </P +><P +> <B +CLASS="COMMAND" +>enc_type</B +> is an encoding type. The value of this field + can be + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_7BIT</B +> + if mechanism is <B +CLASS="COMMAND" +>7bit</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_8BIT</B +> + if mechanism is <B +CLASS="COMMAND" +>8bit</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BINARY</B +> + if mechanism is <B +CLASS="COMMAND" +>binary</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_QUOTED_PRINTABLE</B +> + if mechanism is <B +CLASS="COMMAND" +>quoted-printable</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BASE64</B +> + if mechanism is <B +CLASS="COMMAND" +>base64</B +> or + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_TOKEN</B +> for other. + In case of <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_TOKEN</B +>, + field <B +CLASS="COMMAND" +>enc_token</B +> is filled in. + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_ERROR</B +> is used internally. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_mechanism_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_mechanism_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1784" +></A +><P +><B +>Example 4-5. Creation and display of MIME transfer encoding mechanism</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_QUOTED_PRINTABLE, NULL); + + /* do the things */ + + mailmime_mechanism_free(encoding); +} + +int main(int argc, char ** argv) +{ + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_TOKEN, + strdup("uuencoding")); + + /* do the things */ + + mailmime_mechanism_free(encoding); +} + +void display_mime_mechanism(struct mailmime_mechanism * encoding) +{ + switch (encoding->enc_type) { + case MAILMIME_MECHANISM_7BIT: + printf("7bit\n"); + break; + case MAILMIME_MECHANISM_8BIT: + printf("8bit\n"); + break; + case MAILMIME_MECHANISM_BINARY: + printf("binary\n"); + break; + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + printf("quoted-printable\n"); + break; + case MAILMIME_MECHANISM_BASE64: + printf("base64\n"); + break; + case MAILMIME_MECHANISM_TOKEN: + printf("extension : %s\n", encoding->enc_token); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELDS" +>mailmime_fields - header fields</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_fields { + clist * fld_list; /* list of (struct mailmime_field *) */ +}; + +struct mailmime_fields * mailmime_fields_new(clist * fld_list); + +void mailmime_fields_free(struct mailmime_fields * fields); + </PRE +><P +> This is the header fields of a MIME part. + </P +><P +> <B +CLASS="COMMAND" +>fld_list</B +> is the list of the header fields. + Each element of the list is a <B +CLASS="COMMAND" +>mailmime_field</B +> + (See <A +HREF="x1614.htm#MAILMIME-FIELD" +>the Section called <I +>mailmime_field - MIME header field</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailmime_fields_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_fields_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1799" +></A +><P +><B +>Example 4-6. Creation and display of MIME fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_field * field; + struct mailmime_fields * fields; + clist * list; + struct mailmime_mechanism * encoding; + struct mailmime_disposition * disposition; + + list = clist_new(); + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL); + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, encoding, NULL, NULL, 0, NULL, NULL); + clist_append(list, field); + + field = mailmime_field_new(MAILMIME_FIELD_VERSION, + NULL, NULL, NULL, NULL, 1 << 16, NULL, NULL); + clist_append(list, field); + + /* look at the example in mailmime_disposition to see how to + build a mailmime_disposition */ + disposition = build_mime_disposition(); + field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION, + NULL, NULL, NULL, NULL, 0, disposition, NULL); + clist_append(list, field); + + fields = mailmime_fields_new(list); + + /* do the things */ + + mailmime_fields_free(fields); +} + +void display_mime_fields(struct mailmime_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + display_field(field); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-PARAMETER" +>mailmime_parameter - MIME type parameter</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>struct mailmime_parameter { + char * pa_name; + char * pa_value; +}; + </PRE +><P +> This is the MIME type parameter in + <B +CLASS="COMMAND" +>Content-Type</B +> MIME header + field. For example, this can be + <B +CLASS="COMMAND" +>charset="iso-8859-1"</B +>. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>pa_name</B +> is the name of the parameter, + for example : <B +CLASS="COMMAND" +>charset</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>pa_value</B +> is the value of the parameter, + for example : <B +CLASS="COMMAND" +>iso-8859-1</B +>. + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailmime_parameter_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_parameter_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1821" +></A +><P +><B +>Example 4-7. Creation and display of MIME type parameter</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_parameter * param; + + param = mailmime_parameter_new(strdup("charset"), strdup("iso-8859-1")); + + /* do the things */ + + mailmime_parameter_free(param); +} + +void display_mime_parameter(struct mailmime_parameter * param) +{ + printf("%s = %s\n", param->pa_name, param->pa_value); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-TYPE" +>mailmime_type - MIME main type</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_TYPE_ERROR, + MAILMIME_TYPE_DISCRETE_TYPE, + MAILMIME_TYPE_COMPOSITE_TYPE +}; + +struct mailmime_type { + int tp_type; + union { + struct mailmime_discrete_type * tp_discrete_type; + struct mailmime_composite_type * tp_composite_type; + } tp_data; +}; + +struct mailmime_type * +mailmime_type_new(int tp_type, + struct mailmime_discrete_type * tp_discrete_type, + struct mailmime_composite_type * tp_composite_type); + +void mailmime_type_free(struct mailmime_type * type); + </PRE +><P +> This is the MIME main type (no subtype, no parameter). + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>tp_type</B +>. The value of this field + is either <B +CLASS="COMMAND" +>MAILMIME_TYPE_DISCRETE_TYPE</B +> for MIME discrete type, + or <B +CLASS="COMMAND" +>MAILMIME_TYPE_COMPOSITE_TYPE</B +> for MIME composite type. + <B +CLASS="COMMAND" +>MAILMIME_TYPE_ERROR</B +> is used internally. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>tp_data.tp_discrete_type</B +> is set when <B +CLASS="COMMAND" +>tp_type</B +> + is <B +CLASS="COMMAND" +>MAILMIME_TYPE_DISCRETE_TYPE</B +> + (see <A +HREF="x1614.htm#MAILMIME-DISCRETE-TYPE" +>the Section called <I +>mailmime_discrete_type - MIME discrete type</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>tp_data.tp_composite_type</B +> is set when <B +CLASS="COMMAND" +>tp_type</B +> + is <B +CLASS="COMMAND" +>MAILMIME_TYPE_COMPOSITE_TYPE</B +> + (see <A +HREF="x1614.htm#MAILMIME-COMPOSITE-TYPE" +>the Section called <I +>mailmime_composite_type - Composite MIME type</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailmime_discrete_type_new()</B +> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_discrete_type_free()</B +> frees + memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1851" +></A +><P +><B +>Example 4-8. Creation and display of MIME main type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_type * type; + struct mailmime_discrete_type * discrete_type; + + discrete_type = + mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, NULL); + type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, discrete_type, NULL); + + /* do the things */ + + mailmime_type_free(type); +} + +int main(int argc, char ** argv) +{ + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, composite_type); + + /* do the things */ + + mailmime_type_free(type); +} + +void display_mime_type(struct mailmime_type * type) +{ + printf("mime type:\n"); + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + printf("discrete type:\n"); + display_mime_discrete_type(type->tp_data.tp_discrete_type); + break; + case MAILMIME_TYPE_COMPOSITE_TYPE: + printf("composite type:\n"); + display_mime_composite_type(type->tp_data.tp_composite_type); + break; + } + printf("\n"); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-LANGUAGE" +>mailmime_language - Language of MIME part</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_language { + clist * lg_list; /* atom (char *) */ +}; + +struct mailmime_language * mailmime_language_new(clist * lg_list); + +void mailmime_language_free(struct mailmime_language * lang); + </PRE +><P +> This is the language used in the MIME part. + </P +><P +> <B +CLASS="COMMAND" +>lg_list</B +> is the list of codes of languages used + in the MIME part. This is a list of strings. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_language_new()</B +> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_language_free()</B +> frees + memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1864" +></A +><P +><B +>Example 4-9. Creation and display of language of MIME part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_language * language; + clist * list; + + list = clist_new(); + + clist_append(list, strdup("fr")); + clist_append(list, strdup("en")); + + language = mailmime_language_new(list); + + /* do the things */ + + mailmime_language_free(language); +} + +void display_mime_language(struct mailmime_language * language) +{ + clistiter * cur; + + printf("languages: "); + for(cur = clist_begin(language->lg_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * name; + + name = clist_content(cur); + printf("%s ", name); + } + printf("\n"); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-DATA" +>mailmime_data - Content of MIME part</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_DATA_TEXT, + MAILMIME_DATA_FILE, +}; + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_data { + int dt_type; + int dt_encoding; + int dt_encoded; + union { + struct { + const char * dt_data; + size_t dt_length; + } dt_text; + char * dt_filename; + } dt_data; +}; + +struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, + int dt_encoded, const char * dt_data, size_t dt_length, + char * dt_filename); + +void mailmime_data_free(struct mailmime_data * mime_ </PRE +><P +> This is the content of MIME part, content of + preamble or content of epilogue. + </P +><P +> <B +CLASS="COMMAND" +>dt_type</B +> can be + <B +CLASS="COMMAND" +>MAILMIME_DATA_TEXT</B +> if + the content is a string in memory, + <B +CLASS="COMMAND" +>MAILMIME_DATA_FILE</B +> if the + content is in a file, + </P +><P +> <B +CLASS="COMMAND" +>dt_encoding</B +> is the encoding mechanism + of the part. The value of this field can be + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_7BIT</B +> if mechanism is + <B +CLASS="COMMAND" +>7bit</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_8BIT</B +> if mechanism is + <B +CLASS="COMMAND" +>8bit</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BINARY</B +> if mechanism is + <B +CLASS="COMMAND" +>binary</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_QUOTED_PRINTABLE</B +> if + mechanism is <B +CLASS="COMMAND" +>quoted-printable</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BASE64</B +> if mechanism is + <B +CLASS="COMMAND" +>base64</B +> or + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_TOKEN</B +> for other. If + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_TOKEN</B +>, the part will + be considered as binary. + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_ERROR</B +> is used internally. + </P +><P +> <B +CLASS="COMMAND" +>dt_encoded</B +> is set to 1 if the part is + already encoded with the mechanism given in + <B +CLASS="COMMAND" +>dt_encoding</B +>. It is set to 0 if the part + is already decoded or if it is necessary to encode that part + before rendering it. + </P +><P +> <B +CLASS="COMMAND" +>dt_data.dt_text.dt_data</B +> is a pointer to the + content of the part and <B +CLASS="COMMAND" +>dt_data.dt_text.dt_length</B +> + is the length of the data if <B +CLASS="COMMAND" +>dt_type</B +> is + <B +CLASS="COMMAND" +>MAILMIME_DATA_TEXT</B +>. + </P +><P +> <B +CLASS="COMMAND" +>dt_data.dt_filename</B +> is the name of the file if + <B +CLASS="COMMAND" +>dt_type</B +> is <B +CLASS="COMMAND" +>MAILMIME_DATA_FILE</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_data_new()</B +> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_data_free()</B +> frees + memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1906" +></A +><P +><B +>Example 4-10. Creation and display of MIME part content</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +/* build data with a string */ + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_BASE64, + 0, "foo bar", 7, NULL); + + /* do the things */ + + mailmime_data_free(data); +} + +/* build data with a file */ + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_BASE64, + 0, NULL, 0, strdup("foo.txt")); + + /* do the things */ + + mailmime_data_free(data); +} + +void display_mime_data(struct mailmime_data * data) +{ + switch (data->dt_encoding) { + case MAILMIME_MECHANISM_7BIT: + printf("7bit\n"); + break; + case MAILMIME_MECHANISM_8BIT: + printf("8bit\n"); + break; + case MAILMIME_MECHANISM_BINARY: + printf("binary\n"); + break; + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + printf("quoted-printable\n"); + break; + case MAILMIME_MECHANISM_BASE64: + printf("base64\n"); + break; + case MAILMIME_MECHANISM_TOKEN: + printf("other\n"); + break; + } + + if (data->dt_encoded) + printf("already encoded\n"); + else + printf("not encoded\n"); + + switch (data->dt_type) { + MAILMIME_DATA_TEXT: + printf("data : %p %i\n", data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length); + break; + MAILMIME_DATA_FILE, + printf("data (file) : %s\n", data->dt_data.dt_filename); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME" +>mailmime - MIME part</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_NONE, + MAILMIME_SINGLE, + MAILMIME_MULTIPLE, + MAILMIME_MESSAGE, +}; + +struct mailmime { + /* parent information */ + int mm_parent_type; + struct mailmime * mm_parent; + clistiter * mm_multipart_pos; + + int mm_type; + const char * mm_mime_start; + size_t mm_length; + + struct mailmime_fields * mm_mime_fields; + struct mailmime_content * mm_content_type; + + struct mailmime_data * mm_body; + union { + /* single part */ + struct mailmime_data * mm_single; /* XXX - was body */ + + /* multi-part */ + struct { + struct mailmime_data * mm_preamble; + struct mailmime_data * mm_epilogue; + clist * mm_mp_list; + } mm_multipart; + + /* message */ + struct { + struct mailimf_fields * mm_fields; + struct mailmime * mm_msg_mime; + } mm_message; + + } mm_data; +}; + +struct mailmime * mailmime_new(int mm_type, + const char * mm_mime_start, size_t mm_length, + struct mailmime_fields * mm_mime_fields, + struct mailmime_content * mm_content_type, + struct mailmime_data * mm_body, + struct mailmime_data * mm_preamble, + struct mailmime_data * mm_epilogue, + clist * mm_mp_list, + struct mailimf_fields * mm_fields, + struct mailmime * mm_msg_mime); + +void mailmime_free(struct mailmime * mime); + </PRE +><P +> This describes the MIME structure of a message or a subpart + of a message. + </P +><DIV +CLASS="SECT3" +><H3 +CLASS="SECT3" +><A +NAME="AEN1913" +>common</A +></H3 +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>mm_parent_type</B +>. MIME part type can be + single part, multipart or message part. This describes the MIME part + type of the parent. The value can be + <B +CLASS="COMMAND" +>MAILMIME_NONE</B +> if there is no parent part, + <B +CLASS="COMMAND" +>MAILMIME_SINGLE</B +> if parent is a single part, + <B +CLASS="COMMAND" +>MAILMIME_MULTIPLE</B +> if parent is a multipart, + <B +CLASS="COMMAND" +>MAILMIME_MESSAGE</B +> if parent is a mesage part. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_parent</B +> is the parent MIME structure. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_multipart_pos</B +>. In the case the parent + is a multipart. This is the position in the list of children + of the parent. This position is given by a + <B +CLASS="COMMAND" +>clisiter *</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_type</B +>. This describes the MIME part type + of this part. The value can be + <B +CLASS="COMMAND" +>MAILMIME_SINGLE</B +> if this is a single part, + <B +CLASS="COMMAND" +>MAILMIME_MULTIPLE</B +> if this is a multipart, + <B +CLASS="COMMAND" +>MAILMIME_MESSAGE</B +> if this is a mesage part. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_mime_start</B +>. This is used mostly internally. + This gives the beginning of the header of the MIME part, when this + is parsed from a string in memory. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_length</B +>. This gives the length of the MIME part, + including the MIME header fields. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_mime_fields</B +> is the list of parsed MIME headers + of this part. <B +CLASS="COMMAND" +>Content-Type</B +> must be excluded and stored + in <B +CLASS="COMMAND" +>mm_content_type</B +> instead + (see <A +HREF="x1614.htm#MAILMIME-FIELDS" +>the Section called <I +>mailmime_fields - header fields</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_content_type</B +> is the parsed + <B +CLASS="COMMAND" +>Content-Type</B +> field + (see <A +HREF="x1614.htm#MAILMIME-CONTENT" +>the Section called <I +>mailmime_content - MIME content type (Content-Type)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_body</B +> is the content of the MIME part + (excluding MIME header), when it is parsed from a string + in memory + (see <A +HREF="x1614.htm#MAILMIME-DATA" +>the Section called <I +>mailmime_data - Content of MIME part</I +></A +>). + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT3" +><H3 +CLASS="SECT3" +><A +NAME="AEN1957" +>single part</A +></H3 +><P +></P +><UL +><LI +><P +> When the part is a single part (<B +CLASS="COMMAND" +>mm_type</B +> + is <B +CLASS="COMMAND" +>MAILMIME_SINGLE</B +>). The following fields + are valid. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_data.mm_single</B +> is the content of the + MIME part (excluding MIME header), when it is parsed from a string + in memory. This must have the same + value as <B +CLASS="COMMAND" +>mm_body</B +> when it is set + (see <A +HREF="x1614.htm#MAILMIME-DATA" +>the Section called <I +>mailmime_data - Content of MIME part</I +></A +>). + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT3" +><H3 +CLASS="SECT3" +><A +NAME="AEN1969" +>multipart</A +></H3 +><P +></P +><UL +><LI +><P +> When the part is a multipart (<B +CLASS="COMMAND" +>mm_type</B +> + is <B +CLASS="COMMAND" +>MAILMIME_MULTIPLE</B +>). The following fields + are valid. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_data.mm_multipart.mm_preamble</B +> + is the content of the preamble of the multipart + (see <A +HREF="x1614.htm#MAILMIME-DATA" +>the Section called <I +>mailmime_data - Content of MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_data.mm_multipart.mm_epilogue</B +> + is the content of the epilogue of the multipart + (see <A +HREF="x1614.htm#MAILMIME-DATA" +>the Section called <I +>mailmime_data - Content of MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_data.mm_multipart.mm_mp_list</B +> + is the list of sub parts + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT3" +><H3 +CLASS="SECT3" +><A +NAME="AEN1987" +>message part</A +></H3 +><P +></P +><UL +><LI +><P +> When the part is a message (<B +CLASS="COMMAND" +>mm_type</B +> + is <B +CLASS="COMMAND" +>MAILMIME_MESSAGE</B +>). The following fields + are valid. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_data.mm_message.mm_fields</B +> is the list of + the header fields of the message + (see <A +HREF="x425.htm#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +> in Chapter 3</A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mm_data.mm_message.mm_msg_mime</B +> is + the subpart + of the message part. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT3" +><H3 +CLASS="SECT3" +><A +NAME="AEN2001" +>constructor and destructor</A +></H3 +><P +> <B +CLASS="COMMAND" +>mailmime_new()</B +> creates and + initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_free()</B +> frees + memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2007" +></A +><P +><B +>Example 4-11. Creation and display of MIME part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +/* build one single MIME part */ + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + struct mailmime_data * body; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + /* look at the example in mailmime_content to see how to + build a mailmime_content */ + content_type = build_mime_content(); + + body = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + "foo", 3, NULL); + + mime = mailmime_new(MAILMIME_SINGLE, + NULL, 0, fields, mime_fields, content_type, + body, NULL, NULL, NULL, NULL, NULL); + + /* do the things */ + + mailmime_free(mime); +} + +/* build one single MIME part */ + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + char * str; + struct mailmime_data * body; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + /* look at the example in mailmime_content to see how to + build a mailmime_content */ + content_type = build_mime_content(); + + str = malloc(4); + strcpy(str, "foo"); + + body = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + str, 3, NULL); + + mime = mailmime_new(MAILMIME_SINGLE, + NULL, 0, fields, mime_fields, content_type, + body, NULL, NULL, NULL, NULL, NULL); + + /* do the things */ + + mailmime_free(mime); + free(str); +} + +/* build a MIME part with a sub-message */ + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + char * str; + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, + composite_type); + content_type = mailmime_content_new(type, strdup("rfc2822"), NULL); + + /* build_mime_message() is a function that will build a mime message part */ + sub_mime = build_mime_message(); + + mime = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, fields, mime_fields, content_type, + NULL, NULL, NULL, NULL, sub_mime, NULL); + + /* do the things */ + + mailmime_free(mime); +} + +/* build a MIME part with a sub-message (given by a string) */ + + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + char * str; + struct mailmime_data * msg_content; + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, + composite_type); + content_type = mailmime_content_new(type, strdup("rfc2822"), NULL); + + str = malloc(sizeof(SUB_MESSAGE)); + strcpy(str, SUB_MESSAGE); + + msg_content = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + str, sizeof(SUB_MESSAGE), NULL); + + mime = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, fields, mime_fields, content_type, + NULL, NULL, NULL, NULL, NULL, msg_content); + + /* do the things */ + + mailmime_free(mime); + free(str); +} + +/* build a multipart message */ + + + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + struct mailmime_type * type; + struct mailmime_composite_type * composite_type; + struct mailmime_data * body; + struct mailmime_data * preamble; + struct mailmime_data * epilogue; + clist * list; + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + fields = build_fields(); + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, NULL); + type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, NULL, + composite_type); + content_type = mailmime_content_new(type, strdup("mixed"), NULL); + + list = clist_new(); + /* build_mime_message() is a function that will build a mime message part */ + sub_mime = build_mime_message(); + clist_append(list, sub_mime); + sub_mime = build_mime_message(); + clist_append(list, sub_mime); + + preamble = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + PREAMBLE, sizeof(PREAMBLE), NULL); + + epilogue = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, 0, + EPILOGUE, sizeof(EPILOGUE), NULL); + + mime = mailmime_new(MAILMIME_SINGLE, + NULL, 0, fields, mime_fields, content_type, + NULL, preamble, epilogue, list, NULL, NULL); + + /* do the things */ + + mailmime_free(mime); +} + +/* display mime part info */ + +void display_mime(struct mailmime * mime) +{ + clistiter * cur; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + printf("single part\n"); + break; + case MAILMIME_MULTIPLE: + printf("multipart\n"); + break; + case MAILMIME_MESSAGE: + printf("message\n"); + break; + } + + printf("part : %p, length : %i\n", + mime->mm_mime_start, mime->mm_length); + printf("\n"); + + if (mime->mm_mime_fields != NULL) { + printf("MIME headers :\n"); + display_mime_fields(mime->mm_mime_fields); + printf("\n"); + } + + printf("content type :\n"); + display_content(mime->mm_content_type); + printf("\n"); + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + display_mime_data(mime->mm_data.mm_single); + break; + + case MAILMIME_MULTIPLE: + if (mime->mm_data.mm_multipart.mm_preamble) { + printf("preamble :\n"); + display_mime_data(mime->mm_data.mm_multipart.mm_preamble); + printf("\n"); + } + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + display_mime(clist_content(cur)); + } + + if (mime->mm_data.mm_multipart.mm_epilogue) { + printf("epilogue :\n"); + display_mime_data(mime->mm_data.mm_multipart.mm_epilogue); + printf("\n"); + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_fields) { + printf("headers :\n"); + display_field(mime->mm_data.mm_message.mm_msg_fields); + printf("\n"); + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + printf("sub message %p :\n", + mime->mm_data.mm_message.mm_msg_mime); + display_mime(mime->mm_data.mm_message.mm_msg_mime); + printf("end of sub message %p\n", + mime->mm_data.mm_message.mm_msg_mime); + } + break; + } +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-DISPOSITION" +>mailmime_disposition - MIME disposition information (Content-Disposition)</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_disposition { + struct mailmime_disposition_type * dsp_type; + clist * dsp_parms; /* struct mailmime_disposition_parm */ +}; + </PRE +><P +> This is the parsed <B +CLASS="COMMAND" +>Content-Disposition</B +> + header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>dsp_type</B +> is the type of disposition + (see <A +HREF="x1614.htm#MAILMIME-DISPOSITION-TYPE" +>the Section called <I +>mailmime_disposition_type - Type of MIME disposition</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dsp_parms</B +> is the list of parameters + of <B +CLASS="COMMAND" +>Content-Disposition</B +> header field. + Each element is of type <B +CLASS="COMMAND" +>mailmime_disposition_parm</B +> + (see <A +HREF="x1614.htm#MAILMIME-DISPOSITION-PARM" +>the Section called <I +>mailmime_disposition_parm - MIME disposition parameter</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2026" +></A +><P +><B +>Example 4-12. Creation and display of MIME disposition information</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_disposition * disposition; + struct mailmime_disposition_type * disposition_type; + clist * disposition_parms; + struct mailmime_disposition_parm * param; + + disposition_type = + mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, NULL); + + disposition_parms = clist_new(); + param = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME, + strdup("foo.txt"), NULL, + NULL, NULL, -1, NULL); + clist_append(disposition_parms, param); + + disposition = mailmime_disposition_new(disposition_type, disposition_parms); + + /* do the things */ + + mailmime_disposition_free(disposition); +} + +void display_mime_disposition(struct mailmime_disposition * disposition) +{ + clistiter * cur; + + printf("disposition type:\n"); + display_mailmime_disposition_type(disposition->dsp_type); + printf("\n"); + printf("disposition parameters:\n"); + for(cur = clist_begin(disposition->dsp_parms) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parm * param; + + param = clist_content(cur); + display_mime_disposition_parm(param); + } + printf("\n"); +} + + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-DISPOSITION-TYPE" +>mailmime_disposition_type - Type of MIME disposition</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition_type { + int dsp_type; + char * dsp_extension; +}; + </PRE +><P +> This is the type of MIME disposition. + Parsed <B +CLASS="COMMAND" +>Content-Disposition</B +> field without + parameters. + </P +><P +> <B +CLASS="COMMAND" +>dsp_type</B +> is the type of disposition. + The value can be + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_INLINE</B +> + if MIME disposition is inline, + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_ATTACHMENT</B +> + if MIME disposition is attachment, + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_EXTENSION</B +> + for other. In this case, <B +CLASS="COMMAND" +>dsp_extension</B +> must be + set. + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_ERROR</B +> is used internally. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2041" +></A +><P +><B +>Example 4-13. Creation and display of MIME disposition type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +/* standard disposition type */ + +int main(int argc, char ** argv) +{ + struct mailmime_disposition_type * disposition_type; + + disposition_type = + mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, NULL); + + /* do the things */ + + mailmime_disposition_type_free(disposition_type); +} + +/* disposition type extension */ + +int main(int argc, char ** argv) +{ + struct mailmime_disposition_type * disposition_type; + + disposition_type = + mailmime_disposition_type_new(MAILMIME_DISPOSITION_TYPE_EXTENSION, + strdup("mydisposition")); + + /* do the things */ + + mailmime_disposition_type_free(disposition_type); +} + +void display_mime_disposition_type(struct mailmime_disposition_type * disposition_type) +{ + switch (disposition->dsp_type) { + case MAILMIME_DISPOSITION_TYPE_INLINE: + printf("inline\n"); + break; + case MAILMIME_DISPOSITION_TYPE_ATTACHMENT: + printf("attachment\n"); + break; + case MAILMIME_DISPOSITION_TYPE_EXTENSION: + printf("extension : %s\n", disposition_type->dsp_extension); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-DISPOSITION-PARM" +>mailmime_disposition_parm - MIME disposition parameter</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISPOSITION_PARM_FILENAME, + MAILMIME_DISPOSITION_PARM_CREATION_DATE, + MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, + MAILMIME_DISPOSITION_PARM_READ_DATE, + MAILMIME_DISPOSITION_PARM_SIZE, + MAILMIME_DISPOSITION_PARM_PARAMETER +}; + +struct mailmime_disposition_parm { + int pa_type; + union { + char * pa_filename; + char * pa_creation_date; + char * pa_modification_date; + char * pa_read_date; + size_t pa_size; + struct mailmime_parameter * pa_parameter; + } pa_data; +}; + </PRE +><P +> This is a parameter of MIME disposition information. For + example, this can be + <B +CLASS="COMMAND" +>filename="foo.jpg"</B +>. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>pa_type</B +> is the type of + disposition. The value can be + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_FILENAME</B +> + for a filename parameter, + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_CREATION_DATE</B +> + for a creation date parameter, + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE</B +> + for a modification date parameter, + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_READ_DATE</B +> + for a last read date parameter, + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_SIZE</B +> + for a file size parameter or + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_PARAMETER</B +> + for other parameters. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>pa_data.pa_filename</B +> is the filename + parameter when <B +CLASS="COMMAND" +>pa_type</B +> is + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_FILENAME</B +> + This is a string containing the name of the + file. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>pa_data.pa_creation_date</B +> is the + creation date parameter when <B +CLASS="COMMAND" +>pa_type</B +> is + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_CREATION_DATE</B +>. + This is a string containing the formatted creation date. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>pa_data.pa_modification_date</B +> is the + modification date parameter when <B +CLASS="COMMAND" +>pa_type</B +> is + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE</B +>. + This is a string containing the formatted modification date. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>pa_data.pa_read_date</B +> is the + last read date parameter when <B +CLASS="COMMAND" +>pa_type</B +> is + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_READ_DATE</B +>. + This is a string containing the formatted last read date. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>pa_data.pa_size</B +> is the size + parameter when <B +CLASS="COMMAND" +>pa_type</B +> is + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_SIZE</B +>. + This gives the size of the file. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>pa_data.pa_parameter</B +> is the + name and the value of the parameter when + <B +CLASS="COMMAND" +>pa_type</B +> is + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_PARM_PARAMETER</B +> + (see <A +HREF="x1614.htm#MAILMIME-PARAMETER" +>the Section called <I +>mailmime_parameter - MIME type parameter</I +></A +>) + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2090" +></A +><P +><B +>Example 4-14. Creation and display of MIME disposition + parameter</B +></P +><PRE +CLASS="PROGRAMLISTING" +>int main(int argc, char ** argv) +{ + struct mailmime_disposition_parm * param; + + disposition_parms = clist_new(); + param = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME, + strdup("foo.txt"), NULL, + NULL, NULL, -1, NULL); + /* do the things */ + + mailmime_disposition_parm_free(param); +} + +void display_mime_dsp_parm(struct mailmime_disposition_parm * param) +{ + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + printf("filename: %s\n", param->pa_data.pa_filename); + break; + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + printf("creation date: %s\n", param->pa_data.pa_creation_date); + break; + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + printf("modification date: %s\n", param->pa_data.pa_modification_date); + break; + case MAILMIME_DISPOSITION_PARM_READ_DATE: + printf("read date: %s\n", param->pa_data.pa_read_date); + break; + case MAILMIME_DISPOSITION_PARM_SIZE: + printf("size: %lu\n", (unsigned long) param->pa_data.pa_size); + break; + case MAILMIME_DISPOSITION_PARM_PARAMETER: + printf("MIME disposition param:\n"); + display_mime_parameter(param->pa_data.pa_parameter); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-SINGLE-FIELDS" +>mailmime_single_fields - MIME headers</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_single_fields { + struct mailmime_content * fld_content; + char * fld_content_charset; + char * fld_content_boundary; + char * fld_content_name; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + char * fld_disposition_filename; + char * fld_disposition_creation_date; + char * fld_disposition_modification_date; + char * fld_disposition_read_date; + size_t fld_disposition_size; + struct mailmime_language * fld_language; +}; + +struct mailmime_single_fields * +mailmime_single_fields_new(struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +void mailmime_single_fields_free(struct mailmime_single_fields * + single_fields); + +void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, + struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_fields</B +> (see <A +HREF="x1614.htm#MAILMIME-FIELDS" +>the Section called <I +>mailmime_fields - header fields</I +></A +>) is the native structure + that MIME module will use, this module will provide an easier + structure to use when + parsing fields. <B +CLASS="COMMAND" +>mailmime_single_fields</B +> is + an easier structure to get parsed fields, rather than + iteration over the list of fields. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fld_content</B +> is the MIME content type + (see <A +HREF="x1614.htm#MAILMIME-CONTENT" +>the Section called <I +>mailmime_content - MIME content type (Content-Type)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_content_charset</B +> is the value + of the MIME type parameter <B +CLASS="COMMAND" +>charset</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_content_boundary</B +> is the value + of the MIME type parameter <B +CLASS="COMMAND" +>boundary</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_content_name</B +> is the value + of the MIME type parameter <B +CLASS="COMMAND" +>name</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_encoding</B +> is the MIME encoding + mechanism used + (see <A +HREF="x1614.htm#MAILMIME-MECHANISM" +>the Section called <I +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_id</B +> is the content of the field + <B +CLASS="COMMAND" +>Content-ID</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_description</B +> is the content of the field + <B +CLASS="COMMAND" +>Content-Description</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_version</B +> is the version of MIME + in use. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_disposition</B +> is the MIME + disposition information + (see <A +HREF="x1614.htm#MAILMIME-DISPOSITION" +>the Section called <I +>mailmime_disposition - MIME disposition information (Content-Disposition)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_disposition_filename</B +> is + the <B +CLASS="COMMAND" +>filename</B +> parameter of the + MIME disposition information. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_disposition_creation_date</B +> is + the <B +CLASS="COMMAND" +>creation-date</B +> parameter of the + MIME disposition information. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_disposition_modification_date</B +> is + the <B +CLASS="COMMAND" +>modification-date</B +> parameter of the + MIME disposition information. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_disposition_read_date</B +> is + the <B +CLASS="COMMAND" +>read-date</B +> parameter of the + MIME disposition information. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_disposition_size</B +> is + the <B +CLASS="COMMAND" +>size</B +> parameter of the + MIME disposition information. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_language</B +> is the language + of the MIME part + (see <A +HREF="x1614.htm#MAILMIME-LANGUAGE" +>the Section called <I +>mailmime_language - Language of MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>single_fields</B +> is the structure to fill. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_fields</B +> is the MIME fields list to + use to fill the <B +CLASS="COMMAND" +>single_fields</B +>. + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailmime_single_fields_new()</B +> creates and + initializes a data structure with a + value. Structures given as argument are referenced by the created + object and will <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> be freed if the + object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_single_fields_free()</B +> frees + memory used by the structure and + substructures will <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> be + released. They should be released by + the application. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_single_fields_init()</B +> will + initialize fill the data structure, using + the given argument (<B +CLASS="COMMAND" +>fld_fields</B +> and + <B +CLASS="COMMAND" +>fld_content</B +>). The interesting fields will + be filled into single_fields. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2177" +></A +><P +><B +>Example 4-15. Creation and display of single fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_single_fields * single_fields; + struct mailmime_fields * mime_fields; + struct mailmime_content * content_type; + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + /* look at the example in mailmime_content to see how to + build a mailmime_content */ + content_type = build_mime_content(); + + single_fields = mailmime_single_fields_new(mime_fields, content_type); + + /* do the things */ + + mailmime_single_fields_free(single_fields); + mailmime_fields_free(mime_fields); +} + +void display_mime_single_fields(struct mailmime_single_fields * single_fields) +{ + if (single_fields->fld_content != NULL) { + printf("content type:\n"); + display_mime_content(single_fields->fld_content); + printf("\n"); + } + if (single_fields->fld_content_charset != NULL) { + printf("content type charset: %s\n", + single_fields->fld_content_charset); + printf("\n"); + } + if (single_fields->fld_content_boundary != NULL) { + printf("content type boundary: %s\n", + single_fields->fld_content_boundary); + printf("\n"); + } + if (single_fields->content_name != NULL) { + printf("content type name: %s\n", single_fields->content_name); + printf("\n"); + } + if (single_fields->fld_encoding != NULL) { + printf("content transfer encoding:\n"); + display_mime_mechanism(single_fields->fld_encoding); + printf("\n"); + } + if (single_fields->fld_id != NULL) { + printf("content id: %s\n", single_fields->fld_id); + printf("\n"); + } + if (single_fields->fld_description != NULL) { + printf("content description: %s\n", single_fields->fld_description); + printf("\n"); + } + if (single_fields->fld_version != 0) { + printf("mime version: %i.%i\n", + single_fields->fld_version>> 16, + single_fields->fld_version & 0xFFFF); + printf("\n"); + } + if (single_fields->fld_disposition != NULL) { + printf("content disposition:\n"); + display_mime_disposition(single_fields->fld_disposition); + printf("\n"); + } + if (single_fields->fld_disposition_filename != NULL) { + printf("content disposition filename: %s\n", + single_fields->fld_disposition_filename); + printf("\n"); + } + if (single_fields->fld_disposition_creation_date != NULL) { + printf("content disposition creation date: %s\n", + single_fields->fld_disposition_creation_date); + printf("\n"); + } + if (single_fields->fld_disposition_modification_date != NULL) { + printf("content disposition modification date: %s\n", + single_fields->fld_disposition_modification_date); + printf("\n"); + } + if (single_fields->fld_disposition_read_date != NULL) { + printf("content disposition read date: %s\n", + single_fields->fld_disposition_read_date; + printf("\n"); + } + if (single_fields->fld_disposition_size != (size_t) -1) { + printf("content disposition size : %i\n", + single_fields->fld_disposition_size); + printf("\n"); + } + if (single_fields->language != NULL) { + printf("content language:\n"); + display_mime_language(single_fields->fld_language); + printf("\n"); + } +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="c1586.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x2180.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>MIME</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c1586.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Parser functions</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x2180.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x2180.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,2536 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Parser functions</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="MIME" +HREF="c1586.htm"><LINK +REL="PREVIOUS" +TITLE="Data types" +HREF="x1614.htm"><LINK +REL="NEXT" +TITLE="Rendering of MIME parts" +HREF="x2583.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x1614.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 4. MIME</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x2583.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN2180" +>Parser functions</A +></H1 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-CONTENT-PARSE" +>mailmime_content_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_content_parse(const char * message, size_t length, + size_t * index, + struct mailmime_content ** result); + </PRE +><P +> This function will parse the content of a + <B +CLASS="COMMAND" +>Content-Type</B +> header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME content type. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x1614.htm#MAILMIME-CONTENT" +>the Section called <I +>mailmime_content - MIME content type (Content-Type)</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2203" +></A +><P +><B +>Example 4-16. Parsing MIME content type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Type") == 0) { + struct mailmime_content * content_type; + size_t current_index; + + current_index = 0; + r = mailmime_content_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &content_type); + if (r == MAILIMF_NO_ERROR) { + display_mime_content(content_type); + /* do the things */ + status = EXIT_SUCCESS; + mailmime_content_free(content_type); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-DESCRIPTION-PARSE" +>mailmime_description_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include >libetpan/libetpan.h< + +int mailmime_description_parse(const char * message, size_t length, + size_t * index, + char ** result); + </PRE +><P +> This will parse the content of + <B +CLASS="COMMAND" +>Content-Description</B +> MIME header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME content description. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +>. + The result string must be freed with + <B +CLASS="COMMAND" +>free()</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2227" +></A +><P +><B +>Example 4-17. Parsing MIME description</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Description") == 0) { + char * description; + size_t current_index; + + current_index = 0; + r = mailmime_description_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &description); + if (r == MAILIMF_NO_ERROR) { + printf("%s\n", description); + /* do the things */ + status = EXIT_SUCCESS; + free(description); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-ENCODING-PARSE" +>mailmime_encoding_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include >libetpan/libetpan.h< + +int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result); + </PRE +><P +> This function will parse the content of + <B +CLASS="COMMAND" +>Content-Transfer-Encoding</B +> header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME encoding mechanism. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x1614.htm#MAILMIME-MECHANISM" +>the Section called <I +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2251" +></A +><P +><B +>Example 4-18. parsing MIME encoding mechanism</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Transfer-Encoding") == 0) { + struct mailmime_content * encoding; + size_t current_index; + + current_index = 0; + r = mailmime_encoding_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &encoding); + if (r == MAILIMF_NO_ERROR) { + display_mime_mechanism(encoding); + /* do the things */ + status = EXIT_SUCCESS; + mailmime_mechanism_free(encoding); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELD-PARSE" +>mailmime_field_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int +mailmime_field_parse(struct mailimf_optional_field * field, + struct mailmime_field ** result); + </PRE +><P +> This function will parse a MIME header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>field</B +> is a non-parsed field + (see <A +HREF="x425.htm#MAILIMF-OPTIONAL-FIELD" +>the Section called <I +>mailimf_optional_field - non-standard header</I +> in Chapter 3</A +>). + </P +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x1614.htm#MAILMIME-FIELD" +>the Section called <I +>mailmime_field - MIME header field</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2267" +></A +><P +><B +>Example 4-19. parsing MIME header field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + r = mailmime_field_parse(field->fld_data.fld_optional_field, + &mime_fields); + if (r == MAILIMF_NO_ERROR) { + display_mime_field(mime_field); + mailmime_field_free(mime_field); + status = EXIT_SUCCESS; + } + } + } + + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-ID-PARSE" +>mailmime_id_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include >libetpan/libetpan.h< + +int mailmime_id_parse(const char * message, size_t length, + size_t * index, char ** result); + </PRE +><P +> This will parse the content of + <B +CLASS="COMMAND" +>Content-ID</B +> MIME header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME content identifier. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +>. + The result string must be freed with + <B +CLASS="COMMAND" +>free()</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2291" +></A +><P +><B +>Example 4-20. Parsing MIME content identifier</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-ID") == 0) { + char * id; + size_t current_index; + + current_index = 0; + r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &id); + if (r == MAILIMF_NO_ERROR) { + printf("%s\n", id); + /* do the things */ + status = EXIT_SUCCESS; + free(id); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELDS-PARSE" +>mailmime_fields_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int +mailmime_fields_parse(struct mailimf_fields * fields, + struct mailmime_fields ** result); + </PRE +><P +> This function will parse a MIME header fields. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fields</B +> is a list of RFC 2822 fields + (see <A +HREF="x425.htm#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +> in Chapter 3</A +>). + </P +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x1614.htm#MAILMIME-FIELDS" +>the Section called <I +>mailmime_fields - header fields</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2307" +></A +><P +><B +>Example 4-21. parsing MIME header fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + struct mailmime_fields * mime_fields; + + r = mailmime_fields_parse(f, &mime_fields); + if (r == MAILIMF_NO_ERROR) { + display_mime_fields(mime_fields); + mailmime_fields_free(mime_fields); + status = EXIT_SUCCESS; + } + + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-VERSION-PARSE" +>mailmime_version_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_version_parse(const char * message, size_t length, + size_t * index, + uint32_t * result); + </PRE +><P +> This will parse the content of + <B +CLASS="COMMAND" +>MIME-Version</B +> MIME header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME version. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x1614.htm#MAILMIME-FIELD" +>the Section called <I +>mailmime_field - MIME header field</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2331" +></A +><P +><B +>Example 4-22. parsing MIME version</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "MIME-Version") == 0) { + uint32_t version; + size_t current_index; + + current_index = 0; + r = mailmime_version_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &version); + if (r == MAILIMF_NO_ERROR) { + printf("%i.%i\n", version >> 16, version & 0xFFFF); + /* do the things */ + status = EXIT_SUCCESS; + free(description); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-PARAMETER-PARSE" +>mailmime_parameter_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_parameter_parse(const char * message, size_t length, + size_t * index, + struct mailmime_parameter ** result); + </PRE +><P +> This will parse a MIME parameter (parameter of + <B +CLASS="COMMAND" +>Content-Type</B +> or parameter of + <B +CLASS="COMMAND" +>Content-Disposition</B +>). + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME parameter. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x1614.htm#MAILMIME-PARAMETER" +>the Section called <I +>mailmime_parameter - MIME type parameter</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2356" +></A +><P +><B +>Example 4-23. parsing a MIME parameter</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define PARAM_STR "foo=bar" + +int main(int argc, char ** argv) +{ + int fd; + int r; + size_t current_index; + struct mailmime_parameter * param; + int status; + + status = EXIT_FAILURE; + + current_index = 0; + r = mailmime_parameter_parse(PARAM_STR, sizeof(PARAM_STR) - 1, + ¤t_index, ¶m); + if (r == MAILIMF_NO_ERROR) { + display_mime_parameter(param); + /* do the things */ + mailmime_parameter_free(param); + status = EXIT_SUCCESS; + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-LANGUAGE-PARSE" +>mailmime_language_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_language_parse(const char * message, size_t length, + size_t * index, + struct mailmime_language ** result); + </PRE +><P +> This function will parse the content of a + <B +CLASS="COMMAND" +>Content-Language</B +> header. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME content language. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x1614.htm#MAILMIME-LANGUAGE" +>the Section called <I +>mailmime_language - Language of MIME part</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2380" +></A +><P +><B +>Example 4-24. Parsing the MIME content langage</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Language") == 0) { + struct mailmime_language * lang; + size_t current_index; + + current_index = 0; + r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &lang); + if (r == MAILIMF_NO_ERROR) { + display_mime_language(lang); + /* do the things */ + status = EXIT_SUCCESS; + free(id); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-DISPOSITION-PARSE" +>mailmime_disposition_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_disposition_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition ** result); + </PRE +><P +> This function will parse the content of a + <B +CLASS="COMMAND" +>Content-Disposition</B +> MIME header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME content disposition. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x1614.htm#MAILMIME-DISPOSITION" +>the Section called <I +>mailmime_disposition - MIME disposition information (Content-Disposition)</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2404" +></A +><P +><B +>Example 4-25. Parsing the MIME content disposition</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Disposition") == 0) { + struct mailmime_disposition * dsp; + size_t current_index; + + current_index = 0; + r = mailmime_id_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &dsp); + if (r == MAILIMF_NO_ERROR) { + display_mime_disposition(dsp); + /* do the things */ + status = EXIT_SUCCESS; + free(id); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-DISPOSITION-TYPE-PARSE" +>mailmime_disposition_type_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int +mailmime_disposition_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_type ** + result); + </PRE +><P +> This function will parse the type of MIME content + disposition. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME content disposition type. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x1614.htm#MAILMIME-DISPOSITION-TYPE" +>the Section called <I +>mailmime_disposition_type - Type of MIME disposition</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2427" +></A +><P +><B +>Example 4-26. parsing a MIME content disposition type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define DSP_TYPE_STR "attachment" + +int main(int argc, char ** argv) +{ + int fd; + int r; + size_t current_index; + struct mailmime_disposition_type * dsp_type; + int status; + + status = EXIT_FAILURE; + + current_index = 0; + r = mailmime_disposition_type_parse(DSP_TYPE_STR, sizeof(DSP_TYPE_STR) - 1, + ¤t_index, &dsp_type); + if (r == MAILIMF_NO_ERROR) { + display_mime_disposition_type(dsp_type); + /* do the things */ + mailmime_disposition_type_free(dsp_type); + status = EXIT_SUCCESS; + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-ENCODED-PHRASE-PARSE" +>mailmime_encoded_phrase_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_encoded_phrase_parse(const char * default_fromcode, + const char * message, size_t length, + size_t * index, const char * tocode, + char ** result); + </PRE +><P +> This function will decode a MIME encoded header string, + encoded with RFC 2047. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>default_fromcode</B +> is the default + code to use for parts of string that are not marked + with charset. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is the string to decode. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>tocode</B +> is the destination charset + for decoding. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2455" +></A +><P +><B +>Example 4-27. decoding a MIME encoded header string</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define TEST_STRING "=?iso-8859-1?ab?= =?iso-8859-15?cd?=" + +int main(int argc, char ** argv) +{ + size_t cur_token; + char * decoded_subject; + + cur_token = 0; + mailmime_encoded_phrase_parse("iso-8859-1", + TEST_STRING, sizeof(TEST_STRING), + &cur_token, "iso-8859-1", &decoded_subject); + + printf("%s\n", decoded_subject); + + /* do the things */ + + free(decoded_subject); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-PARSE" +>mailmime_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_parse(const char * message, size_t length, + size_t * index, struct mailmime ** result); + </PRE +><P +> This will parse a MIME message. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string containing + the MIME message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + (see <A +HREF="x1614.htm#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2478" +></A +><P +><B +>Example 4-28. parsing a MIME message</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailmime * mime; + size_t current_index; + + current_index = 0; + r = mailmime_parse(mem, stat_info.st_size, + ¤t_index, &mime); + if (r == MAILIMF_NO_ERROR) { + display_mime(mime); + /* do the things */ + status = EXIT_SUCCESS; + mailmime_free(mime); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-BASE64-BODY-PARSE" +>mailmime_base64_body_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_base64_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + </PRE +><P +> This function will parse a body part encoded using base64. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string encoded using + base64. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + The result must be freed with + <B +CLASS="COMMAND" +>mmap_string_unref()</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2501" +></A +><P +><B +>Example 4-29. Parsing a base64 encoded part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_base64_body_parse(mem, stat_info.st_size, + ¤t_index, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-QUOTED-PRINTABLE-BODY-PARSE" +>mailmime_quoted_printable_body_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_quoted_printable_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len, int in_header); + </PRE +><P +> This function will parse a body part encoded using quoted + printable. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string encoded using + quoted printable. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + The result must be freed with + <B +CLASS="COMMAND" +>mmap_string_unref()</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2524" +></A +><P +><B +>Example 4-30. Parsing a quoted printable encoded part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_quoted_printable_body_parse(mem, stat_info.st_size, + ¤t_index, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-BINARY-BODY-PARSE" +>mailmime_binary_body_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_binary_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + </PRE +><P +> This function will parse a body part encoded using binary + (no encoding). + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string encoded using + binary. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + The result must be freed with + <B +CLASS="COMMAND" +>mmap_string_unref()</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2547" +></A +><P +><B +>Example 4-31. Parsing a binary encoded part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_binary_body_parse(mem, stat_info.st_size, + ¤t_index, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-PART-PARSE" +>mailmime_part_parse</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +int mailmime_part_parse(const char * message, size_t length, + size_t * index, + int encoding, char ** result, size_t * result_len); + </PRE +><P +> This function will parse a body part encoded using a + given MIME encoding mechanism. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>message</B +> is a string encoded using + binary. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the size of the given + string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is a pointer to the start of + the address in the given string, <B +CLASS="COMMAND" +>(* + index)</B +> is modified to point at the end of the + parsed data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>encoding</B +> is a MIME encoding + mechanism. The value can be + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_7BIT</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_8BIT</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BINARY</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_QUOTED_PRINTABLE</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BASE64</B +> or + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_TOKEN</B +> + (see <A +HREF="x1614.htm#MAILMIME-MECHANISM" +>the Section called <I +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>result</B +>. The result of the parse + operation is stored in <B +CLASS="COMMAND" +>(* result)</B +> + The result must be freed with + <B +CLASS="COMMAND" +>mmap_string_unref()</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2580" +></A +><P +><B +>Example 4-32. Parsing a MIME encoded part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + char * result; + size_t result_len; + + current_index = 0; + r = mailmime_part_parse(mem, stat_info.st_size, ¤t_index, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, &result, &result_len); + if (r == MAILIMF_NO_ERROR) { + + /* do the things */ + + mailmime_decoded_part_free(mem); + status = EXIT_SUCCESS; + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x1614.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x2583.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Data types</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c1586.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Rendering of MIME parts</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x229.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x229.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,407 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Buffered I/O</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Tools and datatypes" +HREF="c16.htm"><LINK +REL="PREVIOUS" +TITLE="Hash table" +HREF="x161.htm"><LINK +REL="NEXT" +TITLE="non-buffered I/O" +HREF="x289.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x161.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 2. Tools and datatypes</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x289.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN229" +>Buffered I/O</A +></H1 +><PRE +CLASS="PROGRAMLISTING" +> +#include <libetpan/libetpan.h> + +typedef struct _mailstream mailstream; + </PRE +><P +> streams are objects where we can read data from and write data + to. They are not seekable. That can be for example a pipe or a + network stream. + </P +><PRE +CLASS="PROGRAMLISTING" +>mailstream * mailstream_new(mailstream_low * low, size_t buffer_size); + +int mailstream_close(mailstream * s); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstream_new()</B +> creates a new stream + stream with the low-level (see <A +HREF="x289.htm" +>the Section called <I +>non-buffered I/O</I +></A +>) + stream and a given buffer size. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_close()</B +> closes the stream. + This function will be in charge to free the + <B +CLASS="COMMAND" +>mailstream_low</B +> structure. + </P +><PRE +CLASS="PROGRAMLISTING" +> +ssize_t mailstream_write(mailstream * s, void * buf, size_t count); + +int mailstream_flush(mailstream * s); + +ssize_t mailstream_read(mailstream * s, void * buf, size_t count); + +ssize_t mailstream_feed_read_buffer(mailstream * s); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstream_write()</B +> writes a buffer to the + given stream. This write operation will be buffered. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_flush()</B +> will force a write of + all buffered data for a given stream. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_read()</B +> reads data from the + stream to the given buffer. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_feed_read_buffer()</B +> this function + will just fill the buffer for reading. + </P +><PRE +CLASS="PROGRAMLISTING" +> +mailstream_low * mailstream_get_low(mailstream * s); + +void mailstream_set_low(mailstream * s, mailstream_low * low); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstream_get_low()</B +> returns the low-level + stream of the given stream. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_set_low()</B +> changes the low-level + of the given stream. Useful, for + example, when a stream change from clear stream to SSL + stream. + </P +><PRE +CLASS="PROGRAMLISTING" +>char * mailstream_read_line(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_append(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line); + +char * mailstream_read_multiline(mailstream * s, size_t size, + MMAPString * stream_buffer, + MMAPString * multiline_buffer, + size_t progr_rate, + progress_function * progr_fun); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstream_read_line()</B +> reads an entire line + from the buffer and store it into the + given string. returns <B +CLASS="COMMAND" +>NULL</B +> on error, the + corresponding array + of <B +CLASS="COMMAND" +>char</B +> is returned otherwise. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_read_line_append()</B +> reads an entire + line from the buffer and appends it to the + given string. returns <B +CLASS="COMMAND" +>NULL</B +> on error, the + array of char corresponding to the entire buffer is returned + otherwise. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_read_line_remove_eol()</B +> reads an + entire line from the buffer and store it into the + given string. All CR LF are removed. + returns <B +CLASS="COMMAND" +>NULL</B +> on error, the corresponding + array of <B +CLASS="COMMAND" +>char</B +> is returned otherwise. + </P +><P +> <B +CLASS="COMMAND" +>mailstream_read_multiline()</B +> reads a + multiline data (several lines, the data are ended with + a single period '.') + from the given stream and store it into the given + multiline buffer (multiline_buffer). progr_rate should be 0 + and progr_fun <B +CLASS="COMMAND" +>NULL</B +> (deprecated things). + <B +CLASS="COMMAND" +>stream_buffer</B +> is a buffer used for internal + work of the function. + size should be 0 (deprecated things). + </P +><PRE +CLASS="PROGRAMLISTING" +> +int mailstream_is_end_multiline(char * line); + </PRE +><P +> returns 1 if the line is an end of multiline data (a single + period '.', eventually with CR and/or LF). 0 is returned + otherwise. + </P +><PRE +CLASS="PROGRAMLISTING" +> +int mailstream_send_data(mailstream * s, char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun); + </PRE +><P +> sends multiline data to the given stream. + <B +CLASS="COMMAND" +>size</B +> is the size of the data. + <B +CLASS="COMMAND" +>progr_rate</B +> and <B +CLASS="COMMAND" +>progr_fun</B +> + are deprecated. <B +CLASS="COMMAND" +>progr_rate</B +> must be 0, + <B +CLASS="COMMAND" +>progr_fun</B +> must be NULL. + </P +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILSTREAM-SOCKET" +>socket stream</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>mailstream * mailstream_socket_open(int fd); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstream_socket_open()</B +> will open a + clear-text socket. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILSTREAM-SSL" +>TLS stream</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>mailstream * mailstream_ssl_open(int fd); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstream_ssl_open()</B +> will open a + TLS/SSL socket. + </P +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x161.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x289.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Hash table</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c16.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>non-buffered I/O</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x2583.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x2583.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,529 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Rendering of MIME parts</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="MIME" +HREF="c1586.htm"><LINK +REL="PREVIOUS" +TITLE="Parser functions" +HREF="x2180.htm"><LINK +REL="NEXT" +TITLE="Creation functions" +HREF="x2669.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x2180.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 4. MIME</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x2669.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN2583" +>Rendering of MIME parts</A +></H1 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELDS-WRITE" +>mailmime_fields_write, mailmime_content_write and + mailmime_content_type_write</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields); + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_fields_write</B +> render the MIME + header fields. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_content_write</B +> render the MIME + content type header field. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_content_write</B +> render the + content of the MIME content type header field. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>col</B +> current column is given for wrapping + purpose in <B +CLASS="COMMAND" +>(* col)</B +>, + the resulting columns will be returned.. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>f</B +> is the file descriptor. It can be + stdout for example. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fields</B +> is the header fields + (see <A +HREF="x1614.htm#MAILMIME-FIELDS" +>the Section called <I +>mailmime_fields - header fields</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>content</B +> is the header fields + (see <A +HREF="x1614.htm#MAILMIME-CONTENT" +>the Section called <I +>mailmime_content - MIME content type (Content-Type)</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2610" +></A +><P +><B +>Example 4-33. rendering MIME header fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_mime * mime_fields; + int col; + + /* look at the example in mailmime_fields to see how to + build a mailmime_fields */ + mime_fields = build_mime_fields(); + + col = 0; + mailmime_fields_write(stdout, &col, mime_fields); + + mailmime_fields_free(mime_fields); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + int col; + + /* look at the example in mailmime_content to see how to + build a mailmime_fields */ + content = build_mime_content(); + + col = 0; + mailmime_content_write(stdout, &col, mime_fields); + + mailmime_content_free(content); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + int col; + + /* look at the example in mailmime_content to see how to + build a mailmime_fields */ + content = build_mime_content(); + + col = 0; + mailmime_content_type_write(stdout, &col, mime_fields); + + mailmime_content_free(content); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-WRITE" +>mailmime_write</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info); + </PRE +><P +> This function will render a MIME message. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>col</B +> current column is given for wrapping + purpose in <B +CLASS="COMMAND" +>(* col)</B +>, + the resulting columns will be returned.. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>f</B +> is the file descriptor. It can be + stdout for example. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>build_info</B +> is the MIME message to + render. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-QUOTED-PRINTABLE-WRITE" +>mailmime_quoted_printable_write + and mailmime_base64_write</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size); + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_quoted_printable_write()</B +> will + render a string to quoted printable. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_base64_write()</B +> will + render a string to base64. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>col</B +> current column is given for wrapping + purpose in <B +CLASS="COMMAND" +>(* col)</B +>, + the resulting columns will be returned.. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>f</B +> is the file descriptor. It can be + stdout for example. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>text</B +> is the string to render. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>size</B +> is the size of the string to + render. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2649" +></A +><P +><B +>Example 4-34. render base64 or quoted printable</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + int col; + + col = 0; + mailmime_quoted_printable_write(stdout, &col, + "this is a test", 14); +} + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + int col; + + col = 0; + mailmime_base64_write(stdout, &col, "this is a test", 14); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-DATA-WRITE" +>mailmime_data_write</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_data_write</B +> will + render MIME data. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>col</B +> current column is given for wrapping + purpose in <B +CLASS="COMMAND" +>(* col)</B +>, + the resulting columns will be returned.. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>f</B +> is the file descriptor. It can be + stdout for example. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>data</B +> is the data to render + (see <A +HREF="x1614.htm#MAILMIME-DATA" +>the Section called <I +>mailmime_data - Content of MIME part</I +></A +>). + </P +></LI +></UL +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x2180.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x2669.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Parser functions</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c1586.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Creation functions</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x2669.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x2669.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1656 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Creation functions</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="MIME" +HREF="c1586.htm"><LINK +REL="PREVIOUS" +TITLE="Rendering of MIME parts" +HREF="x2583.htm"><LINK +REL="NEXT" +TITLE="Helper functions" +HREF="x2946.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x2583.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 4. MIME</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x2946.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN2669" +>Creation functions</A +></H1 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-DISPOSITION-NEW-FILENAME" +>mailmime_disposition_new_filename and + mailmime_disposition_new_with_data</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition * +mailmime_disposition_new_filename(int type, char * filename); + +struct mailmime_disposition * +mailmime_disposition_new_with_data(int type, + char * filename, char * creation_date, char * modification_date, + char * read_date, size_t size); + </PRE +><P +> These functions will create a MIME content disposition + information. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>type</B +> a standard MIME disposition : + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_INLINE</B +> or + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_ATTACHMENT</B +>. + </P +><P +> <B +CLASS="COMMAND" +>filename</B +> is the filename. + </P +><P +> <B +CLASS="COMMAND" +>creation_date</B +> is the creation date. + </P +><P +> <B +CLASS="COMMAND" +>modification_date</B +> is the modification + date. + </P +><P +> <B +CLASS="COMMAND" +>read_date</B +> is the last read date. + </P +><P +> <B +CLASS="COMMAND" +>size</B +> is the size of the file. + </P +></LI +><LI +><P +> This will return a MIME content disposition + (see <A +HREF="x1614.htm#MAILMIME-DISPOSITION" +>the Section called <I +>mailmime_disposition - MIME disposition information (Content-Disposition)</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2694" +></A +><P +><B +>Example 4-35. creating a MIME content disposition</B +></P +><PRE +CLASS="PROGRAMLISTING" +> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_disposition * disposition; + + disposition = + mailmime_disposition_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + strdup("foo-bar.txt")); + + /* do the things */ + + mailmime_disposition_free(disposition); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELDS-NEW-EMPTY" +>mailmime_fields_new_empty and mailmime_fields_add</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_fields * mailmime_fields_new_empty(void); + +int mailmime_fields_add(struct mailmime_fields * fields, + struct mailmime_field * field); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_fields_new_empty()</B +> will + create a new empty MIME header fields list. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_fields_add()</B +> will add + MIME header fields to the MIME header fields list. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fields</B +>. The MIME header field will + be added to this MIME header fields list + (see <A +HREF="x1614.htm#MAILMIME-FIELDS" +>the Section called <I +>mailmime_fields - header fields</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>field</B +> is the MIME header field to add + (see <A +HREF="x1614.htm#MAILMIME-FIELD" +>the Section called <I +>mailmime_field - MIME header field</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2713" +></A +><P +><B +>Example 4-36. creating a MIME header fields list</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_fields * fields; + struct mailmime_field * field; + + fields = mailmime_fields_new_empty(); + field = build_mime_field(); + + /* do the things */ + + mailmime_fields_add(fields, field); + + mailmime_fields_free(fields); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELDS-NEW-WITH-DATA" +>mailmime_fields_new_with_data and + mailmime_fields_new_with_version</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_fields * +mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +struct mailmime_fields * +mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_fields_new_with_data()</B +> will + create a MIME header fields list with all the given fields + (<B +CLASS="COMMAND" +>NULL</B +> can be used for the value if the + field must not be present). + <B +CLASS="COMMAND" +>MIME-Version</B +> header field will + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>not</I +></SPAN +> be added. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_fields_new_with_version()</B +> will + create a MIME header fields list with all the given fields + (<B +CLASS="COMMAND" +>NULL</B +> can be used for the value if the + field must not be present). + <B +CLASS="COMMAND" +>MIME-Version</B +> header field will be added. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2728" +></A +><P +><B +>Example 4-37. creating new fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_disposition * disposition; + struct mailmime_fields * mime_fields; + struct mailmime_mechanism * encoding; + + encoding = mailmime_mechanism_new(MAILMIME_MECHANISM_BASE64, NULL); + + disposition = + mailmime_disposition_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + strdup("foo-bar.txt")); + + mime_fields = mailmime_fields_new_with_version(encoding, NULL, + NULL, disposition, NULL); + + /* do the things */ + + mailmime_fields_free(mime_fields); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-GET-CONTENT-MESSAGE" +>mailmime_get_content_message</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime_content * mailmime_get_content_message(void); + +struct mailmime_content * mailmime_get_content_text(void); + +struct mailmime_content * mailmime_content_new_with_str(const char * str); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_get_content_message()</B +> will + create a MIME content type + <B +CLASS="COMMAND" +>message/rfc822</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_get_content_text()</B +> will + create a MIME content type + <B +CLASS="COMMAND" +>plain/text</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_get_content_new_with_str()</B +> will + create a MIME content type given by the string + <B +CLASS="COMMAND" +>plain/text</B +>. + </P +><P +> <B +CLASS="COMMAND" +>str</B +>. This string will + <B +CLASS="COMMAND" +>NOT</B +> be referenced by any structure. + This string will only be parsed to create the structure. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2746" +></A +><P +><B +>Example 4-38. Creating a MIME content type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + + content = mailmime_get_content_message(); + + /* do the things */ + + mailmime_content_free(content); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + /* do the things */ + + mailmime_content_free(content); +} + +int main(int argc, char ** argv) +{ + struct mailmime_content * content; + + content = mailmime_get_content_new_with_str("multipart/mixed"); + + /* do the things */ + + mailmime_content_free(content); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-DATA-NEW-DATA" +>mailmime_data_new_data and mailmime_data_new_file</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_data * +mailmime_data_new_data(int encoding, int encoded, + const char * data, size_t length); + +struct mailmime_data * +mailmime_data_new_file(int encoding, int encoded, + char * filename); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_data_new_data()</B +> will create a + new MIME content, using a string in memory. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_data_new_file()</B +> will create a + new MIME content, using a file. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>encoding</B +> is the MIME encoding + mechanism used to encode this part. The value can be + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_7BIT</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_8BIT</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BINARY</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_QUOTED_PRINTABLE</B +> or + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BASE64</B +> + (see <A +HREF="x1614.htm#MAILMIME-MECHANISM" +>the Section called <I +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>encoded</B +> is set to 1 if the part is + already encoded with the mechanism given in + <B +CLASS="COMMAND" +>encoding</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>data</B +> is a pointer to the + content of the part. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the length of the data. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>filename</B +> is the name of the file. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2779" +></A +><P +><B +>Example 4-39. creating MIME content</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define DATA_STR "my data" + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new_data(MAILMIME_MECHANISM_BASE64, 0, + DATA_STR, sizeof(DATA_STR) - 1); + + /* do the things */ + + mailmime_data_free(data); +} + +int main(int argc, char ** argv) +{ + struct mailmime_data * data; + + data = mailmime_data_new_file(MAILMIME_MECHANISM_BASE64, 0, + strdup("foo-bar.txt")); + + /* do the things */ + + mailmime_data_free(data); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-NEW-MESSAGE-DATA" +>mailmime_new_message_data, mailmime_new_empty and + mailmime_new_with_content</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmime * +mailmime_new_message_data(struct mailmime * msg_mime); + +struct mailmime * +mailmime_new_empty(struct mailmime_content * content, + struct mailmime_fields * mime_fields); + +int +mailmime_new_with_content(const char * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result); + +struct mailmime * mailmime_multiple_new(const char * type); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_new_message_data()</B +> will create a + new MIME message with the given subpart. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_new_empty()</B +> will create a + new MIME part with the given content type and MIME fields + but with no content. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_new_with_content()</B +> will create a + new MIME part with a content type given by a string and a + given MIME fields list. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_multiple_new()</B +> will create a + new MIME multipart with a content type given by a string. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>msg_mime</B +> is the sub part to add to the + MIME message when creating it + (see <A +HREF="x1614.htm#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>content</B +> is the content type of the part + to create + (see <A +HREF="x1614.htm#MAILMIME-CONTENT" +>the Section called <I +>mailmime_content - MIME content type (Content-Type)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>content_type</B +> is the content type of + the part to create given by a string. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mime_fields</B +> is the list of MIME + header fields + (see <A +HREF="x1614.htm#MAILMIME-FIELDS" +>the Section called <I +>mailmime_fields - header fields</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2809" +></A +><P +><B +>Example 4-40. creating a MIME part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define DATA_STR "my data" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailmime * single_part; + + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + mailmime_new_with_content("plain/text", mime_fields, &single_part); + + mailmime_set_body_text(single_part, DATA_STR, sizeof(DATA_STR) - 1); + + mime = mailmime_new_message_data(single_part); + + /* do the things */ + + mailmime_free(mime); +} + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailmime * single_part; + struct mailmime_content * content; + + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + content = mailmime_get_content_text(); + single_part = mailmime_new_empty(content, mime_fields); + + mailmime_set_body_text(single_part, DATA_STR, sizeof(DATA_STR) - 1); + + mime = mailmime_new_message_data(single_part); + + /* do the things */ + + mailmime_free(mime); +} + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + + mime = mailmime_multiple_new("multipart/mixed"); + + /* do the things */ + + mailmime_free(mime); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-SET-PREAMBLE-FILE" +>mailmime_set_preamble_file, mailmime_set_epilogue_file, + mailmime_set_preamble_text and mailmime_set_epilogue_text</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_set_preamble_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_epilogue_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_preamble_text(struct mailmime * build_info, + char * data_str, size_t length); + +int mailmime_set_epilogue_text(struct mailmime * build_info, + char * data_str, size_t length); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_set_preamble_file()</B +> will define + the preamble of a multipart. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_set_preamble_text()</B +> will define + the preamble of a multipart. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_set_epilogue_file()</B +> will define + the epilogue of a multipart. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_set_preamble_text()</B +> will define + the preamble of a multipart. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>build_info</B +> is the MIME part to modify + (see <A +HREF="x1614.htm#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>data_str</B +> is the string to define + as epilogue or prologue. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the length of the string to + define as epilogue or prologue. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>filename</B +> is the name of the file + which content will be defined as epilogue or prologue. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2837" +></A +><P +><B +>Example 4-41. setting preamble and epilogue</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define DATA_STR "test foo bar" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + + mime = mailmime_multiple_new("multipart/mixed"); + + mailmime_set_preamble_file(mime, strdup("foo-bar.txt")); + + mailmime_set_epilogue_data(mime, DATA_STR, sizeof(DATA_STR) - 1); + + /* do the things */ + + mailmime_free(mime); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-SET-BODY-FILE" +>mailmime_set_body_file and mailmime_set_body_text</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_set_body_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_body_text(struct mailmime * build_info, + char * data_str, size_t length); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_set_body_file()</B +> will define + the body of a single part. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_set_body_text()</B +> will define + the body of a single part. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>build_info</B +> is the MIME part to modify + (see <A +HREF="x1614.htm#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>data_str</B +> is the string to define + as the body of the part. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>length</B +> is the length of the string to + define as the body of the part. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>filename</B +> is the name of the file + which content will be defined as the body of the part. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2861" +></A +><P +><B +>Example 4-42. creating a MIME part</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define DATA_STR "my data" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + mailmime_new_with_content("plain/text", mime_fields, &mime); + + mailmime_set_body_text(mime, DATA_STR, sizeof(DATA_STR) - 1); + + + + /* do the things */ + + mailmime_free(mime); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-ADD-PART" +>mailmime_add_part, mailmime_remove_part, + mailmime_smart_add_part and mailmime_smart_remove_part</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_add_part(struct mailmime * build_info, + struct mailmime * part); + +void mailmime_remove_part(struct mailmime * mime); + +int mailmime_smart_add_part(struct mailmime * mime, + struct mailmime * mime_sub); + +int mailmime_smart_remove_part(struct mailmime * mime); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_add_part()</B +> will add a sub MIME + part. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_remove_part()</B +> will detach the + given sub part from its parent. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_smart_add_part()</B +> will add a sub + MIME part. If the parent part is a message and no child + exist, the part is set as the child. If the parent part is a + message and a child already exists, if the child is + multipart, the part to add is added as child of this + multipart, else a multipart is added and the part is added + as child of the multipart. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_smart_remove_part()</B +> will detach + the given sub part from its parent. The sub part will be + freed. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>build_info</B +> is the parent MIME part + (see <A +HREF="x1614.htm#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>part</B +> is the part to add + (see <A +HREF="x1614.htm#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mime</B +> is the parent MIME part + (see <A +HREF="x1614.htm#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mime_sub</B +> is the part to add or to + detach + (see <A +HREF="x1614.htm#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2892" +></A +><P +><B +>Example 4-43. modifying MIME structure</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_add_part(mime, sub_mime); + + /* do the things */ + + mailmime_free(mime); + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime * other_sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + sub_mime = mailmime_new_empty(content, mime_fields); + + content = mailmime_get_content_text(); + mime_fields = + mailmime_fields_new_encoding(MAILMIME_MECHANISM_QUOTED_PRINTABLE); + other_sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_smart_add_part(mime, sub_mime); + mailmime_smart_add_part(mime, other_sub_mime); + + /* do the things */ + + mailmime_free(mime); + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_add_part(mime, sub_mime); + + mailmime_remove_part(sub_mime); + + /* do the things */ + + mailmime_free(sub_mime); + mailmime_free(mime); + +int main(int argc, char ** argv) +{ + struct mailmime * sub_mime; + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + + content = mailmime_get_content_text(); + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + sub_mime = mailmime_new_empty(content, mime_fields); + + mime = mailmime_new_message_data(NULL); + + mailmime_add_part(mime, sub_mime); + + mailmime_smart_remove_part(sub_mime); + + /* do the things */ + + mailmime_free(mime); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-SET-IMF-FIELDS" +>mailmime_set_imf_fields</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +void mailmime_set_imf_fields(struct mailmime * build_info, + struct mailimf_fields * fields); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_set_imf_fields()</B +> will set the + fields of the given MIME message. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>build_info</B +> is the MIME message to + modify + (see <A +HREF="x1614.htm#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fields</B +> is the header fields to set + for the message + (see <A +HREF="x425.htm#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +> in Chapter 3</A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2909" +></A +><P +><B +>Example 4-44. modifying MIME structure</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define DATA_STR "test foo bar" + +int main(int argc, char ** argv) +{ + struct mailmime * mime; + struct mailmime_fields * mime_fields; + struct mailimf_fields * imf_fields; + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT); + + mailmime_new_with_content("text/plain", mime_fields, &mime); + + mailmime_set_body_text(mime, DATA_STR, sizeof(DATA_STR) - 1); + + /* look at the example in mailimf_fields to see how to + build a mailimf_fields */ + imf_fields = build_fields(); + + mailmime_set_imf_fields(mime, imf_fields); + + /* do the things */ + + mailmime_free(mime); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-FIELDS-NEW-ENCODING" +>mailmime_fields_new_encoding and + mailmime_fields_new_filename</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_fields * mailmime_fields_new_encoding(int encoding_type); + +struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, + char * filename, int encoding_type); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_fields_new_encoding()</B +> will + create a list of MIME header fields with only + <B +CLASS="COMMAND" +>Content-Transfer-Encoding</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_fields_new_filename()</B +> will + create a list of MIME header fields with + <B +CLASS="COMMAND" +>Content-Transfer-Encoding</B +> and + <B +CLASS="COMMAND" +>Content-Disposition</B +>. + </P +><P +> The result will be a list of MIME header fields + (see <A +HREF="x1614.htm#MAILMIME-FIELDS" +>the Section called <I +>mailmime_fields - header fields</I +></A +>). + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>encoding_type</B +> is the MIME encoding + mechanism. The value can be + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_7BIT</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_8BIT</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BINARY</B +>, + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_QUOTED_PRINTABLE</B +> or + <B +CLASS="COMMAND" +>MAILMIME_MECHANISM_BASE64</B +> + (see <A +HREF="x1614.htm#MAILMIME-MECHANISM" +>the Section called <I +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dsp_type</B +> is the disposition type. + The value can be + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_INLINE</B +> or + <B +CLASS="COMMAND" +>MAILMIME_DISPOSITION_TYPE_ATTACHMENT</B +> + (see <A +HREF="x1614.htm#MAILMIME-DISPOSITION-TYPE" +>the Section called <I +>mailmime_disposition_type - Type of MIME disposition</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>filename</B +> is the filename for MIME + content disposition. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2943" +></A +><P +><B +>Example 4-45. creating MIME fields with only Content-Transfer-Encoding</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(void) +{ + struct mailmime_fields * fields; + + fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_BASE64); + + /* do the things */ + + mailmime_fields_free(fields); +} + +int main(void) +{ + struct mailmime_fields * fields; + + fields = + mailmime_fields_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + strdup("foo-bar.txt"), MAILMIME_MECHANISM_BASE64); + + /* do the things */ + + mailmime_fields_free(fields); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x2583.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x2946.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Rendering of MIME parts</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c1586.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Helper functions</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x289.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x289.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,245 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>non-buffered I/O</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Tools and datatypes" +HREF="c16.htm"><LINK +REL="PREVIOUS" +TITLE="Buffered I/O" +HREF="x229.htm"><LINK +REL="NEXT" +TITLE="strings" +HREF="x312.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x229.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 2. Tools and datatypes</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x312.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="MAILSTREAM-LOW" +>non-buffered I/O</A +></H1 +><PRE +CLASS="PROGRAMLISTING" +> +#include <libetpan/libetpan.h> + +struct mailstream_low_driver { + ssize_t (* mailstream_read)(mailstream_low *, void *, size_t); + ssize_t (* mailstream_write)(mailstream_low *, void *, size_t); + int (* mailstream_close)(mailstream_low *); + int (* mailstream_get_fd)(mailstream_low *); + void (* mailstream_free)(mailstream_low *); +}; + +typedef struct mailstream_low_driver mailstream_low_driver; + +struct _mailstream_low { + void * data; + mailstream_low_driver * driver; +}; + </PRE +><P +> <B +CLASS="COMMAND" +>mailstream_low</B +> is a non-buffered stream. + </P +><P +> The <B +CLASS="COMMAND" +>mailstream_low_driver</B +> is a set of + functions used to access the stream. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>mailstream_read/write/close()</B +> is the same + interface as <B +CLASS="COMMAND" +>read/write/close()</B +> + system calls, except that the file descriptor is replaced with the + <B +CLASS="COMMAND" +>mailstream_low</B +> structure. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mailstream_get_fd()</B +> returns the file + descriptor used for this non-buffered stream. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>mailstream_free()</B +> is in charge to free + the internal structure of the mailstream_low and the + mailstream_low itself. + </P +></LI +></UL +><PRE +CLASS="PROGRAMLISTING" +> +mailstream_low * mailstream_low_new(void * data, + mailstream_low_driver * driver); + </PRE +><P +> mailstream_low_new() creates a low-level mailstream with the + given internal structure (data) and using the given set of + functions (driver). + </P +><PRE +CLASS="PROGRAMLISTING" +> +ssize_t mailstream_low_write(mailstream_low * s, void * buf, size_t count); + +ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count); + +int mailstream_low_close(mailstream_low * s); + +int mailstream_low_get_fd(mailstream_low * s); + +void mailstream_low_free(mailstream_low * s); + </PRE +><P +> Each of these calls will call the corresponding function defined + in the driver. + </P +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x229.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x312.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Buffered I/O</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c16.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>strings</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x2946.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x2946.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,431 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Helper functions</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="MIME" +HREF="c1586.htm"><LINK +REL="PREVIOUS" +TITLE="Creation functions" +HREF="x2669.htm"><LINK +REL="NEXT" +TITLE="Storages, folders, messages" +HREF="c2988.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x2669.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 4. MIME</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="c2988.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN2946" +>Helper functions</A +></H1 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-TRANSFER-ENCODING-GET" +>mailmime_transfer_encoding_get</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmime_transfer_encoding_get(struct mailmime_fields * fields); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_transfer_encoding_get()</B +> will + return the standard MIME encoding mechanism. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fields</B +> is the list of MIME header + fields. + </P +></LI +><LI +><P +> An integer representing the MIME encoding mechanism will + be returned + (see <A +HREF="x1614.htm#MAILMIME-MECHANISM" +>the Section called <I +>mailmime_mechanism - MIME transfer encoding mechanism (Content-Transfer-Encoding)</I +></A +>). + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2960" +></A +><P +><B +>Example 4-46. extracting MIME encoding mechanism</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + struct mailmime_fields * mime_fields; + + r = mailmime_fields_parse(f, &mime_fields); + if (r == MAILIMF_NO_ERROR) { + int encoding; + + encoding = mailmime_transfer_encoding_get(mime_fields); + + /* do the things */ + + mailmime_fields_free(mime_fields); + status = EXIT_SUCCESS; + } + + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMIME-CONTENT-CHARSET-GET" +>mailmime_content_charset_get and + mailmime_content_param_get</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +char * mailmime_content_charset_get(struct mailmime_content * content); + +char * mailmime_content_param_get(struct mailmime_content * content, + char * name); + +char * mailmime_extract_boundary(struct mailmime_content * content_type); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmime_content_charset_get()</B +> will + return the <B +CLASS="COMMAND" +>charset</B +> parameter of + MIME content type. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_content_param_get()</B +> will + return the value of a given parameter of + MIME content type. + </P +><P +> <B +CLASS="COMMAND" +>mailmime_extract_boundary()</B +> will + return the <B +CLASS="COMMAND" +>charset</B +> parameter of + MIME content type. + </P +><P +></P +><UL +><LI +><P +> + <B +CLASS="COMMAND" +>content</B +> is the MIME content type. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>name</B +> is the name of the parameter to + extract. + </P +></LI +><LI +><P +> With <B +CLASS="COMMAND" +>mailmime_extract_boundary()</B +>, the + returned value must be freed with + <B +CLASS="COMMAND" +>free()</B +>. + </P +></LI +></UL +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN2985" +></A +><P +><B +>Example 4-47. extracting information from MIME content type</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <sys/mman.h> + +int main(int argc, char ** argv) +{ + int fd; + int r; + + status = EXIT_FAILURE; + + fd = open("message.rfc2822", O_RDONLY); + if (fd >= 0) { + void * mem; + struct stat stat_info; + + r = fstat(fd, &stat_info); + if (r >= 0) { + mem = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE); + if (mem != MAP_FAILED) { + struct mailimf_fields * f; + size_t current_index; + + current_index = 0; + r = mailimf_fields_parse(mem, stat_info.st_size, + ¤t_index, &f); + if (r == MAILIMF_NO_ERROR) { + clistiter * cur; + + for(cur = clist_begin(f->fld_list) ; cur != NULL ; cur = + clist_next(cur)) { + struct mailmime_field * mime_field; + struct mailimf_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-Type") == 0) { + struct mailmime_content * content_type; + size_t current_index; + + current_index = 0; + r = mailmime_content_parse(field->fld_data.fld_optional_field->fld_value, + strlen(field->fld_data.fld_optional_field->fld_value), + ¤t_index, &content_type); + if (r == MAILIMF_NO_ERROR) { + char * charset; + char * name; + char * boundary; + + charset = mailmime_content_charset_get(content_type); + name = mailmime_content_param_get(content_type, "name"); + boundary = mailmime_extract_boundary(content_type); + + /* do the things */ + + free(boundary); + + status = EXIT_SUCCESS; + mailmime_content_free(content_type); + } + } + } + } + mailimf_fields_free(f); + } + } + munmap(mem, stat_info.st_size); + } + + close(fd); + } + + exit(status); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x2669.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="c2988.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Creation functions</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c1586.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Storages, folders, messages</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x3011.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x3011.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,208 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Error codes</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Storages, folders, messages" +HREF="c2988.htm"><LINK +REL="PREVIOUS" +TITLE="Storages, folders, messages" +HREF="c2988.htm"><LINK +REL="NEXT" +TITLE="Storage" +HREF="x3015.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="c2988.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 5. Storages, folders, messages</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x3015.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN3011" +>Error codes</A +></H1 +><P +> Error codes returned as integers can be one of the following : + </P +><PRE +CLASS="PROGRAMLISTING" +>enum { + MAIL_NO_ERROR = 0, + MAIL_NO_ERROR_AUTHENTICATED, + MAIL_NO_ERROR_NON_AUTHENTICATED, + MAIL_ERROR_NOT_IMPLEMENTED, + MAIL_ERROR_UNKNOWN, + MAIL_ERROR_CONNECT, + MAIL_ERROR_BAD_STATE, + MAIL_ERROR_FILE, + MAIL_ERROR_STREAM, + MAIL_ERROR_LOGIN, + MAIL_ERROR_CREATE, /* 10 */ + MAIL_ERROR_DELETE, + MAIL_ERROR_LOGOUT, + MAIL_ERROR_NOOP, + MAIL_ERROR_RENAME, + MAIL_ERROR_CHECK, + MAIL_ERROR_EXAMINE, + MAIL_ERROR_SELECT, + MAIL_ERROR_MEMORY, + MAIL_ERROR_STATUS, + MAIL_ERROR_SUBSCRIBE, /* 20 */ + MAIL_ERROR_UNSUBSCRIBE, + MAIL_ERROR_LIST, + MAIL_ERROR_LSUB, + MAIL_ERROR_APPEND, + MAIL_ERROR_COPY, + MAIL_ERROR_FETCH, + MAIL_ERROR_STORE, + MAIL_ERROR_SEARCH, + MAIL_ERROR_DISKSPACE, + MAIL_ERROR_MSG_NOT_FOUND, /* 30 */ + MAIL_ERROR_PARSE, + MAIL_ERROR_INVAL, + MAIL_ERROR_PART_NOT_FOUND, + MAIL_ERROR_REMOVE, + MAIL_ERROR_FOLDER_NOT_FOUND, + MAIL_ERROR_MOVE, + MAIL_ERROR_STARTTLS, + MAIL_ERROR_CACHE_MISS, + MAIL_ERROR_NO_TLS, + MAIL_ERROR_EXPUNGE, + /* misc errors */ + MAIL_ERROR_MISC, + MAIL_ERROR_PROTOCOL, + MAIL_ERROR_CAPABILITY, + MAIL_ERROR_CLOSE, + MAIL_ERROR_FATAL, + MAIL_ERROR_READONLY, + MAIL_ERROR_NO_APOP, + MAIL_ERROR_COMMAND_NOT_SUPPORTED, + MAIL_ERROR_NO_PERMISSION, + MAIL_ERROR_PROGRAM_ERROR, + MAIL_ERROR_SUBJECT_NOT_FOUND, + MAIL_ERROR_CHAR_ENCODING_FAILED, + MAIL_ERROR_SEND, + MAIL_ERROR_COMMAND, +}; + </PRE +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="c2988.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x3015.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Storages, folders, messages</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c2988.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Storage</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x3015.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x3015.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,433 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Storage</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Storages, folders, messages" +HREF="c2988.htm"><LINK +REL="PREVIOUS" +TITLE="Error codes" +HREF="x3011.htm"><LINK +REL="NEXT" +TITLE="Folder" +HREF="x3082.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x3011.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 5. Storages, folders, messages</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x3082.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN3015" +>Storage</A +></H1 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILSTORAGE-DRIVER" +>Storage driver</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +typedef struct mailstorage_driver mailstorage_driver; + +struct mailstorage_driver { + char * sto_name; + int (* sto_connect)(struct mailstorage * storage); + int (* sto_get_folder_session)(struct mailstorage * storage, + char * pathname, mailsession ** result); + void (* sto_uninitialize)(struct mailstorage * storage); +}; + </PRE +><P +> This is the driver for a storage. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>sto_name</B +> is the name of the driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_connect()</B +> connects the storage to + the remote access or to the path in the local filesystem. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_get_folder_session()</B +> can have two + kinds of behaviour. Either it creates a new session and + independant from the session used by the storage and + select the given mailbox or it selects the given mailbox + in the current session. It depends on the efficiency of + the mail access. + </P +><P +> <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>XXX - in the future, this will be moved to the + folder driver</I +></SPAN +> + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_uninitialize()</B +> frees the data + created with mailstorage constructor. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILSTORAGE" +>Storage</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailstorage { + char * sto_id; + void * sto_data; + mailsession * sto_session; + mailstorage_driver * sto_driver; + clist * sto_shared_folders; /* list of (struct mailfolder *) */ + + void * sto_user_data; +}; + </PRE +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>sto_id</B +> is an identifier for the + storage. This can be <B +CLASS="COMMAND" +>NULL</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_data</B +> is the internal data + of the storage. This can only be changed by the driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_session</B +> is the session used by + the storage. The session can be used to send commands. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_driver</B +> is the driver of the + storage. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_shared_folders</B +> is the list of + folders that share the session with the storage. + This is used internally. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sto_user_data</B +> is a field for free + use. The user can store any data in that field. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILSTORAGE-NEW" +>mailstorage_new and mailstorage_free</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailstorage * mailstorage_new(char * sto_id); + +void mailstorage_free(struct mailstorage * storage); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstorage_new()</B +> initializes a storage + structure with an identifier (<B +CLASS="COMMAND" +>sto_id</B +>) and + with no driver. + </P +><P +> <B +CLASS="COMMAND" +>mailstorage_free()</B +> free the memory used + by a storage. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILSTORAGE-CONNECT" +>mailstorage_connect and mailstorage_disconnect</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailstorage_connect(struct mailstorage * storage); + +void mailstorage_disconnect(struct mailstorage * storage); + </PRE +><P +> <B +CLASS="COMMAND" +>mailstorage_connect()</B +> connects the storage. + This function can also be used to confirm that a storage + connection is valid when the storage is already connected. + </P +><P +> <B +CLASS="COMMAND" +>mailstorage_disconnect()</B +> disconnects the + storage. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3074" +>IMAP storage</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int imap_mailstorage_init(struct mailstorage * storage, + char * imap_servername, uint16_t imap_port, + char * imap_command, + int imap_connection_type, int imap_auth_type, + char * imap_login, char * imap_password, + int imap_cached, char * imap_cache_directory); + </PRE +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3077" +>Example</A +></H2 +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN3079" +></A +><P +><B +>Example 5-1. use of storage</B +></P +><PRE +CLASS="PROGRAMLISTING" +>int main(void) +{ + struct mailstorage * storage; + int r; + + storage = mailstorage_new(NULL); + + imap_mailstorage_init(storage, "imap.my-servers.org", 0, + NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN, + "my-login", "my-password", 1, "/home/login/.libetpan/cache"); + + r = mailstorage_connect(storage); + if (r == MAIL_NO_ERROR) { + mailstorage_disconnect(storage); + } + + mailstorage_free(storage); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x3011.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x3082.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Error codes</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c2988.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Folder</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x3082.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x3082.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,691 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Folder</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Storages, folders, messages" +HREF="c2988.htm"><LINK +REL="PREVIOUS" +TITLE="Storage" +HREF="x3015.htm"><LINK +REL="NEXT" +TITLE="Message" +HREF="x3198.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x3015.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 5. Storages, folders, messages</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x3198.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN3082" +>Folder</A +></H1 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILFOLDER-DRIVER" +>Folder driver</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +typedef struct mailfolder_driver mailfolder_driver; + +struct mailfolder_driver { + int (* fld_get_session)(struct mailfolder * folder, + mailsession ** result); + + int (* fld_noop)(struct mailfolder * folder); + + int (* fld_check)(struct mailfolder * folder); + + int (* fld_expunge)(struct mailfolder * folder); + + int (* fld_status)(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + + int (* fld_append_message)(struct mailfolder * folder, + char * message, size_t size); + + int (* fld_get_messages_list)(struct mailfolder * folder, + struct mailmessage_list ** result); + + int (* fld_get_envelopes_list)(struct mailfolder * folder, + struct mailmessage_list * result); + + int (* fld_get_message)(struct mailfolder * folder, + uint32_t num, mailmessage ** result); + + int (* fld_get_message_by_uid)(struct mailfolder * folder, + const char * uid, mailmessage ** result); +} + </PRE +><P +> XXX - this will be implemented in the future. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fld_get_session()</B +> will return the session + this folder should use. + </P +></LI +><LI +><P +> For other method, you should see <A +HREF="x3472.htm#MAILSESSION-DRIVER" +>the Section called <I +>Session driver</I +></A +>. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3095" +>Folder</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailfolder { + char * fld_pathname; + char * fld_virtual_name; + + struct mailstorage * fld_storage; + + mailsession * fld_session; + int fld_shared_session; + clistiter * fld_pos; + + struct mailfolder * fld_parent; + unsigned int fld_sibling_index; + carray * fld_children; /* array of (struct mailfolder *) */ + + void * fld_user_data; +}; + </PRE +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fld_pathname</B +> is the pathname specific to + the driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_virtual_name</B +> is the identifier of + this folder. This can be <B +CLASS="COMMAND" +>NULL</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_storage</B +> is the storage used for this + folder (see <A +HREF="x3015.htm#MAILSTORAGE" +>the Section called <I +>Storage</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_session</B +> is the session used for this + folder. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_shared_session</B +> is set to 1 if the + folder use the same session as the storage. This is used + internally. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_pos</B +> is the + position in the list of folders of the storage. + This is used internally. + </P +></LI +><LI +><P +> use of <B +CLASS="COMMAND" +>fld_parent</B +>, + <B +CLASS="COMMAND" +>fld_sibling_index</B +> and + <B +CLASS="COMMAND" +>fld_children</B +> is deprecated. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_user_data</B +> is a field for free + use. The user can store any data in that field. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILFOLDER-NEW" +>mailfolder_new and mail_folder_free</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailfolder * mailfolder_new(struct mailstorage * fld_storage, + char * fld_pathname, char * fld_virtual_name); + +void mailfolder_free(struct mailfolder * folder); + </PRE +><P +> <B +CLASS="COMMAND" +>mailfolder_new()</B +> initializes a folder + structure with an identifier + (<B +CLASS="COMMAND" +>fld_virtual_name</B +>) with path name + (<B +CLASS="COMMAND" +>fld_pathname</B +>). The folder will be owned + by the given storage (<B +CLASS="COMMAND" +>fld_storage</B +>). + </P +><P +> <B +CLASS="COMMAND" +>mailfolder_free()</B +> free the memory used + by the folder. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILFOLDER-CONNECT" +>mailfolder_connect and mailfolder_disconnect</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailfolder_connect(struct mailfolder * folder); + +void mailfolder_disconnect(struct mailfolder * folder); + </PRE +><P +> <B +CLASS="COMMAND" +>mailfolder_connect()</B +> connects the folder. + This function can also be used to confirm that a folder + connection is valid when the folder is already connected. + When doing operations with several folders, you have to be + sure that this function has been called before making calls + on folder. + </P +><P +> <B +CLASS="COMMAND" +>mailfolder_disconnect()</B +> disconnects the + folder. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILFOLDER-NOOP" +>mailfolder_noop</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailfolder_noop(struct mailfolder * folder); + </PRE +><P +> This function will only send noop to the mail access. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILFOLDER-CHECK" +>mailfolder_check</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailfolder_check(struct mailfolder * folder); + </PRE +><P +> A call to this function will save to disk the internal state + of the selected mailbox (such as flags). + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILFOLDER-EXPUNGE" +>mailfolder_expunge</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailfolder_expunge(struct mailfolder * folder); + </PRE +><P +> A call to this function will delete all messages marked for + deletion. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILFOLDER-STATUS" +>mailfolder_status</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int mailfolder_status(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + </PRE +><P +> A call to this function will return some counts of messages + in the mailbox. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILFOLDER-APPEND-MESSAGE" +>mailfolder_append_message</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int mailfolder_append_message(struct mailfolder * folder, + char * message, size_t size); + </PRE +><P +> This function will store a new message in the given folder. + The message is given by a string in memory + (<B +CLASS="COMMAND" +>message</B +>) and a size + (<B +CLASS="COMMAND" +>size</B +>). + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILFOLDER-GET-MESSAGES-LIST" +>mailfolder_get_messages_list</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int mailfolder_get_messages_list(struct mailfolder * folder, + struct mailmessage_list ** result); + </PRE +><P +> This function will return the list of messages in the given + folder (see <A +HREF="x3198.htm#MAILMESSAGE-LIST" +>the Section called <I +>Message list</I +></A +>). + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILFOLDER-GET-ENVELOPES-LIST" +>mailfolder_get_envelopes_list</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int mailfolder_get_envelopes_list(struct mailfolder * folder, + struct mailmessage_list * result); + </PRE +><P +> This function will fill the list of parsed header fields + structure in the <B +CLASS="COMMAND" +>mailmessage</B +> structures + of the given list of messages (<B +CLASS="COMMAND" +>result</B +>). + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILFOLDER-GET-MESSAGE" +>mailfolder_get_message</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int mailfolder_get_message(struct mailfolder * folder, + uint32_t num, mailmessage ** result); + </PRE +><P +> This function will return the message identified by a + message index (<B +CLASS="COMMAND" +>num</B +>) + This will return a <B +CLASS="COMMAND" +>mailmessage</B +> structure + in <B +CLASS="COMMAND" +>(* result)</B +> (see <A +HREF="x3198.htm#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>). + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILFOLDER-GET-MESSAGE-BY-UID" +>mailfolder_get_message_by_uid</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int mailfolder_get_message_by_uid(struct mailfolder * folder, + const char * uid, mailmessage ** result); + </PRE +><P +> This function will return the message identified by a + unique identifier (<B +CLASS="COMMAND" +>uid</B +>) + This will return a <B +CLASS="COMMAND" +>mailmessage</B +> structure + in <B +CLASS="COMMAND" +>(* result)</B +> (see <A +HREF="x3198.htm#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>). + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3193" +>Example</A +></H2 +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN3195" +></A +><P +><B +>Example 5-2. use of folder</B +></P +><PRE +CLASS="PROGRAMLISTING" +>int main(void) +{ + struct mailstorage * storage; + int r; + + storage = mailstorage_new(NULL); + + imap_mailstorage_init(storage, "imap.my-servers.org", 0, + NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN, + "my-login", "my-password", 1, "/home/login/.libetpan/cache"); + + r = mailstorage_connect(storage); + if (r == MAIL_NO_ERROR) { + struct mailfolder * folder; + + folder = mailfolder_new(storage, "INBOX", NULL); + + r = mailfolder_connect(folder); + if (r == MAIL_NO_ERROR) { + struct mailmessage_list * msg_list; + + mailfolder_get_messages_list(folder, &msg_list); + + /* do the things */ + + mailmessage_list_free(msg_list); + + mailfolder_disconnect(folder); + } + + mailstorage_disconnect(storage); + } + + mailstorage_free(storage); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x3015.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x3198.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Storage</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c2988.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Message</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x312.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x312.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,477 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>strings</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Tools and datatypes" +HREF="c16.htm"><LINK +REL="PREVIOUS" +TITLE="non-buffered I/O" +HREF="x289.htm"><LINK +REL="NEXT" +TITLE="Internet Message Format" +HREF="c385.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x289.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 2. Tools and datatypes</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="c385.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN312" +>strings</A +></H1 +><PRE +CLASS="PROGRAMLISTING" +> +#include <libetpan/libetpan.h> + +struct _MMAPString +{ + char * str; + size_t len; + size_t allocated_len; + int fd; + size_t mmapped_size; +}; + +typedef struct _MMAPString MMAPString; + </PRE +><P +> MMAPString is a string which size that can increase automatically. + </P +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MMAP-STRING-NEW" +>constructor and destructor</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>MMAPString * mmap_string_new(const char * init); + +MMAPString * mmap_string_new_len(const char * init, size_t len); + +MMAPString * mmap_string_sized_new(size_t dfl_size); + +void mmap_string_free(MMAPString * string); + </PRE +><P +> <B +CLASS="COMMAND" +>mmap_string_new()</B +> allocates a new + string. init is the intial value of the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_new_len()</B +> allocates a new + string. init is the intial value of the + string, len is the length of the initial string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_sized_new()</B +> allocates a new + string. dfl_size is the initial allocation of + the string. <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_free()</B +> release the memory used + by the string. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MMAP-STRING-ASSIGN" +>string value modification</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>MMAPString * mmap_string_assign(MMAPString * string, const char * rval); + +MMAPString * mmap_string_truncate(MMAPString *string, size_t len); + </PRE +><P +> <B +CLASS="COMMAND" +>mmap_string_assign()</B +> sets a new value for + the given string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_truncate()</B +> sets a length for + the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + </P +><PRE +CLASS="PROGRAMLISTING" +>MMAPString * mmap_string_set_size (MMAPString * string, size_t len); + </PRE +><P +> sets the allocation of the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MMAP-STRING-APPEND" +>insertion in string, deletion in string</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>MMAPString * mmap_string_insert_len(MMAPString * string, size_t pos, + const char * val, size_t len); + +MMAPString * mmap_string_append(MMAPString * string, const char * val); + +MMAPString * mmap_string_append_len(MMAPString * string, + const char * val, size_t len); + +MMAPString * mmap_string_append_c(MMAPString * string, char c); + +MMAPString * mmap_string_prepend(MMAPString * string, const char * val); + +MMAPString * mmap_string_prepend_c(MMAPString * string, char c); + +MMAPString * mmap_string_prepend_len(MMAPString * string, const char * val, + size_t len); + +MMAPString * mmap_string_insert(MMAPString * string, size_t pos, + const char * val); + +MMAPString * mmap_string_insert_c(MMAPString *string, size_t pos, + char c); + +MMAPString * mmap_string_erase(MMAPString * string, size_t pos, + size_t len); + </PRE +><P +> For complexity here, n is the size of the given MMAPString, + and len is the size of the string to insert. + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_insert_len()</B +> inserts the given + string value of given length in the string at the given + position. <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(n + len). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_append()</B +> appends the given + string value at the end of the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(len). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_append_len()</B +> appends the + given string value of given length at the end of the + string. <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(len). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_append_c()</B +> appends the given + character at the end of the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_prepend()</B +> insert the given + string value at the beginning of the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(n + len). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_prepend_c()</B +> insert the given + character at the beginning of the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(n). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_prepend_len()</B +> insert the given + string value of given length at the beginning of the string. + <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(n + len). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_insert()</B +> inserts the given + string value in the string at the given position. + NULL will be returned on error. + Complexity is O(n + len). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_insert_c()</B +> inserts the given + character in the string at the given position. + NULL will be returned on error. + Complexity is O(n). + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_erase()</B +> removes the given + count of characters (len) at the given position of the + string. <B +CLASS="COMMAND" +>NULL</B +> will be returned on error. + Complexity is O(n). + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MMAP-STRING-REF" +>referencing string</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int mmap_string_ref(MMAPString * string); + +int mmap_string_unref(char * str); + </PRE +><P +> MMAPString provides a mechanism that let you use MMAPString + like normal strings. You have first to use + <B +CLASS="COMMAND" +>mmap_string_ref()</B +>, so that you notify + that the string will be used as a normal string, then, you + use <B +CLASS="COMMAND" +>mmapstr->str</B +> to refer to the + string. When you have finished and you want to free a string + corresponding to a <B +CLASS="COMMAND" +>MMAPString</B +>, you will + use <B +CLASS="COMMAND" +>mmap_string_unref</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mmap_string_ref()</B +> references the string + so that the array of characters can be used as a normal + string then released with + <B +CLASS="COMMAND" +>mmap_string_unref()</B +>. + The array of characters will be obtained with string->str. + returns -1 on error, 0 on success. + </P +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x289.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="c385.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>non-buffered I/O</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c16.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Internet Message Format</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x3198.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x3198.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1785 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Message</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Storages, folders, messages" +HREF="c2988.htm"><LINK +REL="PREVIOUS" +TITLE="Folder" +HREF="x3082.htm"><LINK +REL="NEXT" +TITLE="Session" +HREF="x3472.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x3082.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 5. Storages, folders, messages</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x3472.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN3198" +>Message</A +></H1 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-DRIVER" +>Message driver</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmessage_driver { + char * msg_name; + + int (* msg_initialize)(mailmessage * msg_info); + + void (* msg_uninitialize)(mailmessage * msg_info); + + void (* msg_flush)(mailmessage * msg_info); + + void (* msg_check)(mailmessage * msg_info); + + void (* msg_fetch_result_free)(mailmessage * msg_info, + char * msg); + + int (* msg_fetch)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_header)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_body)(mailmessage * msg_info, + char ** result, size_t * result_len); + + int (* msg_fetch_size)(mailmessage * msg_info, + size_t * result); + + int (* msg_get_bodystructure)(mailmessage * msg_info, + struct mailmime ** result); + + int (* msg_fetch_section)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + + int (* msg_fetch_section_header)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_mime)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_body)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_envelope)(mailmessage * msg_info, + struct mailimf_fields ** result); + + int (* msg_get_flags)(mailmessage * msg_info, + struct mail_flags ** result); +}; + </PRE +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>msg_name</B +> is the name of the driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_initialize()</B +> will initialize the + internal message state (field + <B +CLASS="COMMAND" +>msg_data</B +> of + <B +CLASS="COMMAND" +>mailmessage</B +> structure (see <A +HREF="x3198.htm#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_uninitialize()</B +> will free the + internal message state. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_flush()</B +> will release memory used + by the MIME structure of the message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_check()</B +> will store the flags of + the message into the session, so that the message can be + released without the flags are lost. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_result_free()</B +> will free a + string returned by any fetch_XXX() function. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch()</B +> will fetch a message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_header()</B +> will fetch the + header fields of a message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_body()</B +> will fetch a message + without its main header. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_size()</B +> will return the size + of a message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_get_bodystructure</B +> will retrieve + the MIME structure of the message. The returned + structure must <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> be freed. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_section()</B +> will fetch the + content of the section of the message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_section_header()</B +> will fetch + the header of a section of the message if the content of + the section is a message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_section_mime()</B +> will fetch + the MIME header of a section of the message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_section_body()</B +> will fetch + the body of a section (without the headers) of the + message if the content of the section is a message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fetch_envelope()</B +> will return + a given number of parsed header fields. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_get_flags()</B +> will return the + flags of the message. + The returned structure must <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> be + freed. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE" +>Message</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmessage { + mailsession * msg_session; + mailmessage_driver * msg_driver; + uint32_t msg_index; + char * msg_uid; + + size_t msg_size; + struct mailimf_fields * msg_fields; + struct mail_flags * msg_flags; + + int msg_resolved; + struct mailimf_single_fields msg_single_fields; + struct mailmime * msg_mime; + + /* internal data */ + + int msg_cached; + void * msg_data; + + /* + msg_folder field : + used to reference the mailfolder, this is a workaround due + to the problem with initial conception, where folder notion + did not exist. + */ + void * msg_folder; + /* user data */ + void * msg_user_data; +}; + </PRE +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>msg_session</B +> is the session related to + the message + (see <A +HREF="x3472.htm#MAILSESSION" +>the Section called <I +>Session</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_driver</B +> is the driver used for the + message + (see <A +HREF="x3198.htm#MAILMESSAGE-DRIVER" +>the Section called <I +>Message driver</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_index</B +> is an index to indentify + the message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_uid</B +> is the unique identifier of + the message, valid accross disconnections. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_size</B +> is the size of the message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_fields</B +> is the list of parsed + header fields of the message. This can be + <B +CLASS="COMMAND" +>NULL</B +> + (see <A +HREF="x425.htm#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +> in Chapter 3</A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_flags</B +> is the flags of the + message. This can be <B +CLASS="COMMAND" +>NULL</B +> + (see <A +HREF="x3198.htm#MAIL-FLAGS" +>the Section called <I +>Message flags</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_resolved</B +> will tell if the field + <B +CLASS="COMMAND" +>msg_single_fields</B +> has been initialized. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_single_fields</B +> will be filled + using <B +CLASS="COMMAND" +>msg_fields</B +> + (see <A +HREF="x425.htm#MAILIMF-SINGLE-FIELDS" +>the Section called <I +>mailimf_single_fields - simplified fields</I +> in Chapter 3</A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_mime</B +> is the MIME structure of the + message. It is intialized at least when + <B +CLASS="COMMAND" +>get_bodystructure()</B +> is called once. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_cached</B +> is 1 when the message was + cached. This is used internally. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_data</B +> is the internal state of the + message. The content depends on the driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_folder</B +> is used to reference the + mailfolder, this is a workaround due to the problem with + initial conception, where folder notion did not exist. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_user_data</B +> is a field for free + use. The user can store any data in that field. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-NEW" +>mailmessage_new</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +mailmessage * mailmessage_new(void); + +void mailmessage_free(mailmessage * info); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmessage_new()</B +> will create a new + message (without driver). This is used internally by + drivers. + </P +><P +> <B +CLASS="COMMAND" +>mailmessage_free()</B +> will free the memory + used by the given message. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-INIT" +>mailmessage_init</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_init(mailmessage * msg_info, + mailsession * session, + mailmessage_driver * driver, + uint32_t index, size_t size); + </PRE +><P +> <B +CLASS="COMMAND" +>mailmessage_init()</B +> will initialize a + message with a driver. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>msg_info</B +> is the message to initialize + (see <A +HREF="x3198.htm#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>session</B +> is the session related to the + message + (see <A +HREF="x3472.htm#MAILSESSION" +>the Section called <I +>Session</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>driver</B +> is the driver to use for the + message + (see <A +HREF="x3198.htm#MAILMESSAGE-DRIVER" +>the Section called <I +>Message driver</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>index</B +> is the index of the message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>size</B +> is the size of the message. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FLUSH" +>mailmessage_flush</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_flush(mailmessage * info); + </PRE +><P +> This function will release the memory used by the MIME + structure of the message. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-CHECK" +>mailmessage_check</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_check(mailmessage * info); + </PRE +><P +> After you set some flags, if you want to notify them to the + session before destroying the message, you can use this function. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-RESULT-FREE" +>mailmessage_fetch_result_free</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_result_free(mailmessage * msg_info, + char * msg); + </PRE +><P +> This function will free a string returned by any + mailmessage_fetch_XXX() function. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH" +>mailmessage_fetch</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + </PRE +><P +> This function returns the content of the message (headers + and text). + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-HEADER" +>mailmessage_fetch_header</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + </PRE +><P +> This function returns the header of the message as a string. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-BODY" +>mailmessage_fetch_body</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + </PRE +><P +> This function returns the content of the message (without + headers). + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-SIZE" +>mailmessage_fetch_size</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_size(mailmessage * msg_info, + size_t * result); + </PRE +><P +> This function returns the size of the message content. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-GET-BODYSTRUCTURE" +>mailmessage_get_bodystructure</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + </PRE +><P +> This functions returns the MIME structure of the message. + The returned information <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>MUST</I +></SPAN +> not be + freed by hand. It is freed by + <B +CLASS="COMMAND" +>mailmessage_flush()</B +> or + <B +CLASS="COMMAND" +>mailmessage_free()</B +> + (see <A +HREF="x1614.htm#MAILMIME" +>the Section called <I +>mailmime - MIME part</I +> in Chapter 4</A +>). + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-SECTION" +>mailmessage_fetch_section</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + </PRE +><P +> This function returns the content of a MIME part. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-SECTION-HEADER" +>mailmessage_fetch_section_header</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + </PRE +><P +> This function returns the header of the message contained + in the given MIME part. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-SECTION-MIME" +>mailmessage_fetch_section_mime</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + </PRE +><P +> This function returns the MIME header of the given MIME + part. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-SECTION-BODY" +>mailmessage_fetch_section_body</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + </PRE +><P +> This function returns the text part of the message contained + in the given MIME part. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-FETCH-ENVELOPE" +>mailmessage_fetch_envelope</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + </PRE +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-GET-FLAGS" +>mailmessage_get_flags</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailmessage_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + </PRE +><P +> This function returns the flags related to the message. + The returned information MUST not be freed by hand. It is freed by + <B +CLASS="COMMAND" +>mailmessage_free()</B +>. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-RESOLVE-SINGLE-FIELDS" +>mailmessage_resolve_single_fields</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +void mailmessage_resolve_single_fields(mailmessage * msg_info); + </PRE +><P +> This function will use the fields information to fill + the single_fields structure in the mailmessage structure. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-LIST" +>Message list</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmessage_list { + carray * msg_tab; /* elements are (mailmessage *) */ +}; + +struct mailmessage_list * mailmessage_list_new(carray * msg_tab); + +void mailmessage_list_free(struct mailmessage_list * env_list); + </PRE +><P +> This is a list of messages. + </P +><P +> <B +CLASS="COMMAND" +>msg_tab</B +> is an array containing the + messages (see linkend="carray"). + </P +><P +> <B +CLASS="COMMAND" +>mailmessage_list_new()</B +> will initialize a + list of messages, using a given array of messages. + </P +><P +> <B +CLASS="COMMAND" +>mailmessage_list_free()</B +> will free the + memory used by the list of messages. This will also free the + messages. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILMESSAGE-TREE" +>Message tree</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailmessage_tree { + struct mailmessage_tree * node_parent; + char * node_msgid; + time_t node_date; + mailmessage * node_msg; + carray * node_children; /* array of (struct mailmessage_tree *) */ + + /* private, used for threading */ + int node_is_reply; + char * node_base_subject; +}; + + +struct mailmessage_tree * +mailmessage_tree_new(char * node_msgid, time_t node_date, + mailmessage * node_msg); + +void mailmessage_tree_free(struct mailmessage_tree * tree); + +void mailmessage_tree_free_recursive(struct mailmessage_tree * tree); + </PRE +><P +> This is a node of a tree of messages. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>node_parent</B +> is the parent of this + node. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>node_msgid</B +> is the content of the + field <B +CLASS="COMMAND" +>Message-ID</B +> of the message. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>node_date</B +> is the date in UNIX + format. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>node_msg</B +> is the message of the node. + The message should have the <B +CLASS="COMMAND" +>msg_fields</B +> + field initialized. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>node_children</B +> is the list of + children of this node. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>node_is_reply</B +> is set to 1 if the + message is a reply. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>node_base_subject</B +> is the base subject + of the message (base subject is defined in definition of + IMAP thread draft). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailmessage_tree_new()</B +> will initialize a + message node. + </P +><P +> <B +CLASS="COMMAND" +>mailmessage_tree_free()</B +> will release + memory used by the node. This will <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> + free the message. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAIL-FLAGS" +>Message flags</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAIL_FLAG_NEW = 1 << 0, + MAIL_FLAG_SEEN = 1 << 1, + MAIL_FLAG_FLAGGED = 1 << 2, + MAIL_FLAG_DELETED = 1 << 3, + MAIL_FLAG_ANSWERED = 1 << 4, + MAIL_FLAG_FORWARDED = 1 << 5, + MAIL_FLAG_CANCELLED = 1 << 6, +}; + +struct mail_flags { + uint32_t fl_flags; + clist * fl_extension; /* elements are (char *) */ +}; + +struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_ext); + +void mail_flags_free(struct mail_flags * flags); + +int mail_flags_add_extension(struct mail_flags * flags, + char * ext_flag); + +int mail_flags_remove_extension(struct mail_flags * flags, + char * ext_flag); + +int mail_flags_has_extension(struct mail_flags * flags, + char * ext_flag); + </PRE +><P +> This is the structure containing the message flags. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fl_flags</B +> will contain the standards + flags. The value will be a combinaison (with or binary + operation) of <B +CLASS="COMMAND" +>MAIL_FLAG_XXX</B +> values. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fl_extension</B +> will be a list (see + <A +HREF="x88.htm" +>the Section called <I +>List</I +> in Chapter 2</A +>) of strings representing the + non-standard flags. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3467" +>Example</A +></H2 +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN3469" +></A +><P +><B +>Example 5-3. use of message</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +#define DEST_CHARSET "iso-8859-1" + +enum { + NO_ERROR, + ERROR_FILE, + ERROR_MEMORY, + ERROR_INVAL, + ERROR_FETCH, +}; + +/* returns TRUE is given MIME part is a text part */ + +int etpan_mime_is_text(struct mailmime * build_info) +{ + if (build_info->mm_type == MAILMIME_SINGLE) { + if (build_info->mm_content_type != NULL) { + if (build_info->mm_content_type->ct_type->tp_type == + MAILMIME_TYPE_DISCRETE_TYPE) { + if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type == + MAILMIME_DISCRETE_TYPE_TEXT) + return 1; + } + } + else + return 1; + } + + return 0; +} + + +/* display content type */ + +int show_part_info(FILE * f, + struct mailmime_single_fields * mime_fields, + struct mailmime_content * content) +{ + char * description; + char * filename; + int col; + int r; + + description = mime_fields->fld_description; + filename = mime_fields->fld_disposition_filename; + + col = 0; + + r = fprintf(f, " [ Part "); + if (r < 0) + goto err; + + if (content != NULL) { + r = mailmime_content_type_write(f, &col, content); + if (r != MAILIMF_NO_ERROR) + goto err; + } + + if (filename != NULL) { + r = fprintf(f, " (%s)", filename); + if (r < 0) + goto err; + } + + if (description != NULL) { + r = fprintf(f, " : %s", description); + if (r < 0) + goto err; + } + + r = fprintf(f, " ]\n\n"); + if (r < 0) + goto err; + + return NO_ERROR; + + err: + return ERROR_FILE; +} + +/* fetch message and decode if it is base64 or quoted-printable */ + +int etpan_fetch_message(mailmessage * msg_info, + struct mailmime * mime_part, + struct mailmime_single_fields * fields, + char ** result, size_t * result_len) +{ + char * data; + size_t len; + int r; + int encoding; + char * decoded; + size_t decoded_len; + size_t cur_token; + int res; + int encoded; + + encoded = 0; + + r = mailmessage_fetch_section(msg_info, + mime_part, &data, &len); + if (r != MAIL_NO_ERROR) { + res = ERROR_FETCH; + goto err; + } + + encoded = 1; + + /* decode message */ + + if (encoded) { + if (fields->fld_encoding != NULL) + encoding = fields->fld_encoding->enc_type; + else + encoding = MAILMIME_MECHANISM_8BIT; + } + else { + encoding = MAILMIME_MECHANISM_8BIT; + } + + cur_token = 0; + r = mailmime_part_parse(data, len, &cur_token, + encoding, &decoded, &decoded_len); + if (r != MAILIMF_NO_ERROR) { + res = ERROR_FETCH; + goto free; + } + + mailmessage_fetch_result_free(msg_info, data); + + * result = decoded; + * result_len = decoded_len; + + return NO_ERROR; + + free: + mailmessage_fetch_result_free(msg_info, data); + err: + return res; +} + +/* fetch fields */ + +struct mailimf_fields * fetch_fields(mailmessage * msg_info, + struct mailmime * mime) +{ + char * data; + size_t len; + int r; + size_t cur_token; + struct mailimf_fields * fields; + + r = mailmessage_fetch_section_header(msg_info, mime, + &data, &len); + if (r != MAIL_NO_ERROR) + return NULL; + + cur_token = 0; + r = mailimf_envelopes_fields_parse(data, len, + &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + mailmessage_fetch_result_free(msg_info, data); + return NULL; + } + + mailmessage_fetch_result_free(msg_info, data); + + return fields; +} + +/* render message */ + +static int etpan_render_mime(FILE * f, mailmessage * msg_info, + struct mailmime * mime) +{ + int r; + clistiter * cur; + int col; + int text; + int show; + struct mailmime_single_fields fields; + int res; + + mailmime_single_fields_init(&fields, mime->mm_mime_fields, + mime->mm_content_type); + + text = etpan_mime_is_text(mime); + + r = show_part_info(f, &fields, mime->mm_content_type); + if (r != NO_ERROR) { + res = r; + goto err; + } + + switch(mime->mm_type) { + case MAILMIME_SINGLE: + show = 0; + if (text) + show = 1; + + if (show) { + char * data; + size_t len; + char * converted; + size_t converted_len; + char * source_charset; + size_t write_len; + + /* viewable part */ + + r = etpan_fetch_message(msg_info, mime, + &fields, &data, &len); + if (r != NO_ERROR) { + res = r; + goto err; + } + + source_charset = fields.fld_content_charset; + if (source_charset == NULL) + source_charset = DEST_CHARSET; + + r = charconv_buffer(source_charset, DEST_CHARSET, + data, len, &converted, &converted_len); + if (r != MAIL_CHARCONV_NO_ERROR) { + + r = fprintf(f, "[ error converting charset from %s to %s ]\n", + source_charset, DEST_CHARSET); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + + write_len = fwrite(data, 1, len, f); + if (write_len != len) { + mailmime_decoded_part_free(data); + res = r; + goto err; + } + } + else { + write_len = fwrite(converted, 1, converted_len, f); + if (write_len != len) { + charconv_buffer_free(converted); + mailmime_decoded_part_free(data); + res = r; + goto err; + } + + charconv_buffer_free(converted); + } + + write_len = fwrite("\r\n\r\n", 1, 4, f); + if (write_len < 4) { + mailmime_decoded_part_free(data); + res = ERROR_FILE; + goto err; + } + + mailmime_decoded_part_free(data); + } + else { + /* not viewable part */ + + r = fprintf(f, " (not shown)\n\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + break; + + case MAILMIME_MULTIPLE: + + if (strcasecmp(mime->mm_content_type->ct_subtype, + "alternative") == 0) { + struct mailmime * prefered_body; + int prefered_score; + + /* case of multiple/alternative */ + + /* + we choose the better part, + alternative preference : + + text/plain => score 3 + text/xxx => score 2 + other => score 1 + */ + + prefered_body = NULL; + prefered_score = 0; + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * submime; + int score; + + score = 1; + submime = clist_content(cur); + if (etpan_mime_is_text(submime)) + score = 2; + + if (submime->mm_content_type != NULL) { + if (strcasecmp(submime->mm_content_type->ct_subtype, + "plain") == 0) + score = 3; + } + + if (score > prefered_score) { + prefered_score = score; + prefered_body = submime; + } + } + + if (prefered_body != NULL) { + r = etpan_render_mime(f, msg_info, prefered_body); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + else { + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + + r = etpan_render_mime(f, msg_info, clist_content(cur)); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + + break; + + case MAILMIME_MESSAGE: + + if (mime->mm_data.mm_message.mm_fields != NULL) { + struct mailimf_fields * fields; + + if (msg_info != NULL) { + fields = fetch_fields(msg_info, mime); + if (fields == NULL) { + res = ERROR_FETCH; + goto err; + } + + col = 0; + r = mailimf_fields_write(f, &col, fields); + if (r != NO_ERROR) { + mailimf_fields_free(fields); + res = r; + goto err; + } + + mailimf_fields_free(fields); + } + else { + col = 0; + r = fields_write(f, &col, mime->mm_data.mm_message.mm_fields); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + r = fprintf(f, "\r\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + r = etpan_render_mime(f, msg_info, + mime->mm_data.mm_message.mm_msg_mime); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + break; + } + + return NO_ERROR; + + err: + return res; +} + + + +int main(void) +{ + struct mailstorage * storage; + int r; + + storage = mailstorage_new(NULL); + + imap_mailstorage_init(storage, "imap.my-servers.org", 0, + NULL, CONNECTION_TYPE_TRY_STARTTLS, IMAP_AUTH_TYPE_PLAIN, + "my-login", "my-password", 1, "/home/login/.libetpan/cache"); + + r = mailstorage_connect(storage); + if (r == MAIL_NO_ERROR) { + struct mailfolder * folder; + + folder = mailfolder_new(storage, "INBOX", NULL); + + r = mailfolder_connect(folder); + if (r == MAIL_NO_ERROR) { + struct mailmessage_list * msg_list; + mailmessage * msg; + + mailfolder_get_messages_list(folder, &msg_list); + + if (carray_count(msg_list->msg_tab) > 0) { + struct mailmime * mime; + + msg = carray_get(msg_list->msg_tab, 0); + + mailmessage_get_bodystructure(msg, &mime); + + recursive_fetch(msg, mime); + + /* do the things */ + + mailmessage_flush(msg); + } + mailmessage_list_free(msg_list); + + mailfolder_disconnect(folder); + } + + mailstorage_disconnect(storage); + } + + mailstorage_free(storage); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x3082.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x3472.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Folder</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c2988.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Session</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x3472.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x3472.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1361 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Session</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Storages, folders, messages" +HREF="c2988.htm"><LINK +REL="PREVIOUS" +TITLE="Message" +HREF="x3198.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x3198.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 5. Storages, folders, messages</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +> </TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN3472" +>Session</A +></H1 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILSESSION-DRIVER" +>Session driver</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailsession_driver { + char * sess_name; + + int (* sess_initialize)(mailsession * session); + void (* sess_uninitialize)(mailsession * session); + + int (* sess_parameters)(mailsession * session, + int id, void * value); + + int (* sess_connect_stream)(mailsession * session, mailstream * s); + int (* sess_connect_path)(mailsession * session, char * path); + + int (* sess_starttls)(mailsession * session); + + int (* sess_login)(mailsession * session, char * userid, char * password); + int (* sess_logout)(mailsession * session); + int (* sess_noop)(mailsession * session); + + /* folders operations */ + + int (* sess_build_folder_name)(mailsession * session, char * mb, + char * name, char ** result); + + int (* sess_create_folder)(mailsession * session, char * mb); + int (* sess_delete_folder)(mailsession * session, char * mb); + int (* sess_rename_folder)(mailsession * session, char * mb, + char * new_name); + int (* sess_check_folder)(mailsession * session); + int (* sess_examine_folder)(mailsession * session, char * mb); + int (* sess_select_folder)(mailsession * session, char * mb); + int (* sess_expunge_folder)(mailsession * session); + int (* sess_status_folder)(mailsession * session, char * mb, + uint32_t * result_num, uint32_t * result_recent, + uint32_t * result_unseen); + int (* sess_messages_number)(mailsession * session, char * mb, + uint32_t * result); + int (* sess_recent_number)(mailsession * session, char * mb, + uint32_t * result); + int (* sess_unseen_number)(mailsession * session, char * mb, + uint32_t * result); + + int (* sess_list_folders)(mailsession * session, char * mb, + struct mail_list ** result); + int (* sess_lsub_folders)(mailsession * session, char * mb, + struct mail_list ** result); + + int (* sess_subscribe_folder)(mailsession * session, char * mb); + int (* sess_unsubscribe_folder)(mailsession * session, char * mb); + + /* messages operations */ + + int (* sess_append_message)(mailsession * session, + char * message, size_t size); + int (* sess_copy_message)(mailsession * session, + uint32_t num, char * mb); + int (* sess_move_message)(mailsession * session, + uint32_t num, char * mb); + + int (* sess_get_message)(mailsession * session, + uint32_t num, mailmessage ** result); + + int (* sess_get_message_by_uid)(mailsession * session, + const char * uid, mailmessage ** result); + + int (* sess_get_messages_list)(mailsession * session, + struct mailmessage_list ** result); + int (* sess_get_envelopes_list)(mailsession * session, + struct mailmessage_list * env_list); + int (* sess_remove_message)(mailsession * session, uint32_t num); +}; + </PRE +><P +> This is a driver for a session. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>sess_name</B +> is the name of the driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_initialize()</B +> is the function + that will initializes a data structure (field + <B +CLASS="COMMAND" +>sess_data</B +> in the session) specific to + the driver. + The field data (field <B +CLASS="COMMAND" +>sess_data</B +> in + the session) is the state of the session, + the internal data structure used by the driver. + It is called when creating the + <B +CLASS="COMMAND" +>mailsession</B +> structure with + <B +CLASS="COMMAND" +>mailsession_new()</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_uninitialize()</B +> frees the structure + created with <B +CLASS="COMMAND" +>sess_initialize()</B +> + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_parameters()</B +> implements + functions specific to the given mail access. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_connect_stream()</B +> connects a + stream to the session. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_connect_path()</B +> notify a main + path to the session. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_starttls()</B +> changes the current + stream to a TLS stream + (see <A +HREF="x229.htm#MAILSTREAM-SSL" +>the Section called <I +>TLS stream</I +> in Chapter 2</A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_login()</B +> notifies the user and + the password to authenticate to the session. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_logout()</B +> exits the session and + closes the stream. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_noop()</B +> does no operation on the + session, but it can be used to poll for the status of + the connection. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_build_folder_name()</B +> will return an + allocated string with that contains the complete path of + the folder to create. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_create_folder()</B +> creates the + folder that corresponds to the given name. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_delete_folder()</B +> deletes the folder + that corresponds to the given name. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_rename_folder()</B +> change the name + of the folder. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_check_folder()</B +> makes a + checkpoint of the session. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_examine_folder()</B +> selects a mailbox as + readonly. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_select_folder()</B +> selects a mailbox. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_expunge_folder()</B +> deletes all + messages marked \Deleted. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_status_folder()</B +> queries the + status of the folder (number of messages, number of + recent messages, number of unseen messages). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_messages_number()</B +> queries the + number of messages in the folder. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_recent_number()</B +> queries the + number of recent messages in the folder. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_unseen_number()</B +> queries the number of + unseen messages in the folder. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_list_folders()</B +> returns the list of + all sub-mailboxes of the given mailbox. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_lsub_folders()</B +> returns the list of + subscribed sub-mailboxes of the given mailbox. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_subscribe_folder()</B +> subscribes to + the given mailbox. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_unsubscribe_folder()</B +> unsubscribes to + the given mailbox. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_append_message()</B +> adds a RFC 2822 + message to the current given mailbox. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_copy_message()</B +> copies a message + whose number is given to a given mailbox. The mailbox + must be accessible from the same session. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_move_message()</B +> moves a message whose + number is given to + a given mailbox. The mailbox must be accessible from the + same session. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_get_messages_list()</B +> returns the list + of message numbers + of the current mailbox + (see <A +HREF="x3198.htm#MAILMESSAGE-LIST" +>the Section called <I +>Message list</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_get_envelopes_list()</B +> fills the parsed + fields in the <B +CLASS="COMMAND" +>mailmessage</B +> structures + (see <A +HREF="x3198.htm#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>) + of the <B +CLASS="COMMAND" +>mailmessage_list</B +> + (see <A +HREF="x3198.htm#MAILMESSAGE-LIST" +>the Section called <I +>Message list</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_remove_message()</B +> removes the given + message from the mailbox. + The message is permanently deleted. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_get_message()</B +> returns a + mailmessage structure + (see <A +HREF="x3198.htm#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>) + that corresponds + to the given message number. + <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>Use of this method is deprecated</I +></SPAN +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_get_message_by_uid()</B +> returns a + mailmessage structure + (see <A +HREF="x3198.htm#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>) + that corresponds + to the given message unique identifier. + </P +></LI +></UL +><P +> mandatory functions are the following : + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>sess_connect_stream()</B +> or + <B +CLASS="COMMAND" +>connect_path()</B +> + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_logout()</B +> + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_get_messages_list()</B +> + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_get_envelopes_list()</B +> + </P +></LI +></UL +><P +> we advise you to implement these functions : + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>sess_select_folder()</B +> (in case a session + can access several folders). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_noop()</B +> (to check if the server is + responding) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_check_folder()</B +> (to make a checkpoint + of the session) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_status_folder()</B +>, + <B +CLASS="COMMAND" +>sess_messages_number()</B +>, + <B +CLASS="COMMAND" +>sess_recent_number()</B +>, + <B +CLASS="COMMAND" +>sess_unseen_number()</B +> + (to get stat of the folder) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_append_message()</B +> (but can't be done + in the case of POP3 at least). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_login()</B +> in a case of an + authenticated driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_starttls()</B +> in a case of a stream + driver, if the procotol supports STARTTLS. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_get_message_by_uid()</B +> so that the + application can remember the messages + by UID and build its own list of messages. + </P +></LI +><LI +><P +> Everything that is specific to the driver will be + implemented in <B +CLASS="COMMAND" +>sess_parameters()</B +>. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILSESSION" +>Session</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailsession { + void * sess_data; + mailsession_driver * sess_driver; +}; + +mailsession * mailsession_new(mailsession_driver * sess_driver); + +void mailsession_free(mailsession * session); + </PRE +><P +> This is a session. This is an abstraction used to access the + storage, using the network or the filesystem. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>sess_data</B +> is the state of the + session. This is specific to the driver. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>sess_driver</B +> is the driver of the + session. + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailsession_new()</B +> will create a new session + using the given driver (<B +CLASS="COMMAND" +>sess_driver</B +>). + </P +><P +> <B +CLASS="COMMAND" +>mailsession_free()</B +> will release the memory + used by the session. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3670" +>mailsession_parameters</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_parameters(mailsession * session, + int id, void * value); + </PRE +><P +> This function make calls specific to the driver + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3674" +>mailsession_connect_stream</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_connect_stream(mailsession * session, mailstream * s); + </PRE +><P +> There are drivers of two kinds : stream drivers (driver that + connects to servers through TCP or other means of connection) + and file drivers (driver that are based on filesystem) + + This function can only be used by stream drivers and + this connects a stream to the session + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3678" +>mailsession_connect_path</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_connect_path(mailsession * session, char * path); + </PRE +><P +> This function can only be used by file drivers and + selects the main path of the session. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3682" +>mailsession_starttls</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_starttls(mailsession * session); + </PRE +><P +> This switches the current connection to TLS (secure layer). + This will only work with stream drivers. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3686" +>mailsession_login</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_login(mailsession * session, + char * userid, char * password); + </PRE +><P +> This notifies the login and the password to authenticate + to the session. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3690" +>mailsession_logout</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_logout(mailsession * session); + </PRE +><P +> This function disconnects the session and closes the stream. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3694" +>mailsession_noop</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_noop(mailsession * session); + </PRE +><P +> This function does no operation on the session, but it can be + used to poll for the status of the connection. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3698" +>mailsession_check_folder</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_check_folder(mailsession * session); + </PRE +><P +> This function makes a checkpoint of the session. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3702" +>mailsession_select_folder</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_select_folder(mailsession * session, char * mb); + </PRE +><P +> This function selects a mailbox. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3706" +>mailsession_expunge_folder</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_expunge_folder(mailsession * session); + </PRE +><P +> This function deletes all messages marked for deletion. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3710" +>mailsession_status_folder</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_status_folder(mailsession * session, char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + </PRE +><P +> This function queries the status of the folder + (number of messages, number of recent messages, number of + unseen messages). + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3714" +>mailsession_messages_number</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_messages_number(mailsession * session, char * mb, + uint32_t * result); + </PRE +><P +> This function queries the number of messages in the folder. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3718" +>mailsession_recent_number</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_recent_number(mailsession * session, + char * mb, uint32_t * result); + </PRE +><P +> This function queries the number of recent messages in the + folder. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3722" +>mailsession_unseen_number</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_unseen_number(mailsession * session, char * mb, + uint32_t * result); + </PRE +><P +> This function queries the number of unseen messages in the + folder. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3726" +>mailsession_append_message</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_append_message(mailsession * session, + char * message, size_t size); + </PRE +><P +> This adds a RFC 2822 message to the current mailbox. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3730" +>mailsession_get_messages_list</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + </PRE +><P +> This function returns the list of messages + of the current mailbox. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3734" +>mailsession_get_envelopes_list</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_get_envelopes_list(mailsession * session, + struct mailmessage_list * result); + </PRE +><P +> This function fills the parsed fields in the + <B +CLASS="COMMAND" +>mailmessage</B +> structures + (see <A +HREF="x3198.htm#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>) + of the mailmessage_list + (see <A +HREF="x3198.htm#MAILMESSAGE-LIST" +>the Section called <I +>Message list</I +></A +>). + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3741" +>mailsession_get_message</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + </PRE +><P +> This function returns a <B +CLASS="COMMAND" +>mailmessage</B +> + (see <A +HREF="x3198.htm#MAILMESSAGE" +>the Section called <I +>Message</I +></A +>) structure that + corresponds to the given message number. + </P +><DIV +CLASS="WARNING" +><P +></P +><TABLE +CLASS="WARNING" +BORDER="1" +WIDTH="100%" +><TR +><TD +ALIGN="CENTER" +><B +>Warning</B +></TD +></TR +><TR +><TD +ALIGN="LEFT" +><P +> <B +CLASS="COMMAND" +>mailsession_get_message_by_uid()</B +> should + be used instead. + </P +></TD +></TR +></TABLE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="AEN3750" +>mailsession_get_message_by_uid</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int mailsession_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + </PRE +><P +> This function returns a mailmessage structure + that corresponds to the given message unique identifier. + This is currently implemented only for cached drivers. + </P +><DIV +CLASS="WARNING" +><P +></P +><TABLE +CLASS="WARNING" +BORDER="1" +WIDTH="100%" +><TR +><TD +ALIGN="CENTER" +><B +>Warning</B +></TD +></TR +><TR +><TD +ALIGN="LEFT" +><P +> That deprecates the use of + <B +CLASS="COMMAND" +>mailsession_get_message()</B +>. + </P +></TD +></TR +></TABLE +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x3198.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +> </TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Message</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c2988.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +> </TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x425.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x425.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,4306 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Data types</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Internet Message Format" +HREF="c385.htm"><LINK +REL="PREVIOUS" +TITLE="Internet Message Format" +HREF="c385.htm"><LINK +REL="NEXT" +TITLE="Parser functions" +HREF="x1094.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="c385.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 3. Internet Message Format</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x1094.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AEN425" +>Data types</A +></H1 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-MAILBOX" +>mailimf_mailbox - mailbox</A +></H2 +><P +>#include <libetpan/libetpan.h> + +struct mailimf_mailbox { + char * mb_display_name; /* can be NULL */ + char * mb_addr_spec; /* != NULL */ +}; + +struct mailimf_mailbox * +mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec); + +void mailimf_mailbox_free(struct mailimf_mailbox * mailbox); + </P +><P +> This is an email mailbox with a display name. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN431" +></A +><P +><B +>Example 3-1. example of mailbox</B +></P +><PRE +CLASS="PROGRAMLISTING" +>DINH Viet Hoa <hoa@users.sourceforge.net> + </PRE +></DIV +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_new</B +> creates and + initializes a data structure with a value. + Strings given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_free</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN438" +></A +><P +><B +>Example 3-2. mailbox creation and display</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_mailbox * mb; + char * display_name; + char * address; + + display_name = strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="); + address = strdup("dinh.viet.hoa@free.fr"); + mb = mailimf_mailbox_new(str, address); + /* do the things */ + mailimf_mailbox_free(mb); + + return 0; +} + +/* display mailbox information */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_mailbox(struct mailimf_mailbox * mb) +{ + if (mb->mb_display_name != NULL) + printf("display name: %s\n", mb->mb_display_name); + printf("address specifier : %s\n", mb->mb_addr_spec); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-ADDRESS" +>mailimf_address - address</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_address { + int ad_type; + union { + struct mailimf_mailbox * ad_mailbox; /* can be NULL */ + struct mailimf_group * ad_group; /* can be NULL */ + } ad_data; +}; + +struct mailimf_address * +mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox, + struct mailimf_group * ad_group); + +void mailimf_address_free(struct mailimf_address * address); + </PRE +><P +> This is a mailbox or a group of mailbox. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>ad_type</B +> can be MAILIMF_ADDRESS_MAILBOX or + <B +CLASS="COMMAND" +>MAILIMF_ADDRESS_GROUP</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>ad_data.ad_mailbox</B +> is a mailbox if + <B +CLASS="COMMAND" +>ad_type</B +> is + <B +CLASS="COMMAND" +>MAILIMF_ADDRESS_MAILBOX</B +> + see <A +HREF="x425.htm#MAILIMF-MAILBOX" +>the Section called <I +>mailimf_mailbox - mailbox</I +></A +>) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>ad_data.group</B +> is a group if type is + <B +CLASS="COMMAND" +>MAILIMF_ADDRESS_GROUP</B +>. + see <A +HREF="x425.htm#MAILIMF-GROUP" +>the Section called <I +>mailimf_group - named group of mailboxes</I +></A +>) + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_address_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_address_free</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN465" +></A +><P +><B +>Example 3-3. address creation and display</B +></P +><PRE +CLASS="PROGRAMLISTING" +>/* creates an address of type mailbox */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_address * a_mb; + struct mailimf_mailbox * mb; + char * display_name; + char * address; + + display_name = strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="); + address = strdup("dinh.viet.hoa@free.fr"); + mb = mailimf_mailbox_new(str, address); + + a_mb = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + /* do the things */ + mailimf_address_free(a_mb); +} + +/* creates an address of type group */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_address * a_g; + struct mailimf_group * g; + char * display_name; + + display_name = strdup("undisclosed-recipient"); + g = mailimf_group_new(display_name, NULL); + + a_g = mailimf_address_new(MAILIMF_ADDRESS_GROUP, NULL, g); + /* do the things */ + mailimf_address_free(a_g); + + return 0; +} + +/* display the content of an address */ + +#include <libetpan/libetpan.h> + +void display_address(struct mailimf_address * a) +{ + clistiter * cur; + + switch (a->ad_type) { + case MAILIMF_ADDRESS_GROUP: + display_mailimf_group(a->ad_data.ad_group); + break; + + case MAILIMF_ADDRESS_MAILBOX: + display_mailimf_mailbox(a->ad_data.ad_mailbox); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-MAILBOX-LIST" +>mailimf_mailbox_list - list of mailboxes</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_mailbox_list { + clist * mb_list; /* list of (struct mailimf_mailbox *), != NULL */ +}; + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new(clist * mb_list); + +void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list); + </PRE +><P +> This is a list of mailboxes. + </P +><P +> <B +CLASS="COMMAND" +>mb_list</B +> is a list of mailboxes. This is a + <B +CLASS="COMMAND" +>clist</B +> which elements are of type + mailimf_mailbox (see <A +HREF="x425.htm#MAILIMF-MAILBOX" +>the Section called <I +>mailimf_mailbox - mailbox</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_list_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_mailbox_list_free()</B +> frees memory used by the + structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN480" +></A +><P +><B +>Example 3-4. Creation and display of mailimf_mailbox_list</B +></P +><PRE +CLASS="PROGRAMLISTING" +>/* creates a list of mailboxes with two mailboxes */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_group * g; + char * display_name; + struct mailimf_mailbox_list * mb_list; + clist * list; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + list = clist_append(mb); + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + list = clist_append(mb); + + mb_list = mailimf_mailbox_list_new(list); + /* do the things */ + mailimf_mailbox_list_free(mb_list); + + return 0; +} + +/* display a list of mailboxes */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_mailbox_list(struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + display_mailbox(mb); + printf("\n"); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-ADDRESS-LIST" +>mailimf_address_list - list of addresses</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_address_list { + clist * ad_list; /* list of (struct mailimf_address *), != NULL */ +}; + +struct mailimf_address_list * +mailimf_address_list_new(clist * ad_list); + +void mailimf_address_list_free(struct mailimf_address_list * addr_list); + </PRE +><P +> This is a list of addresses. + </P +><P +> <B +CLASS="COMMAND" +>ad_list</B +> is a list of addresses. This is a + <B +CLASS="COMMAND" +>clist</B +> which elements are + of type mailimf_address (see <A +HREF="x425.htm#MAILIMF-ADDRESS" +>the Section called <I +>mailimf_address - address</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_address_list_new()</B +> creates and + initializes a data structure with + a value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_address_list_free()</B +> frees memory + used by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN495" +></A +><P +><B +>Example 3-5. creation and display of list of addresses</B +></P +><PRE +CLASS="PROGRAMLISTING" +>/* creates a list of addresses with two addresses */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_address_list * addr_list; + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + list = clist_append(addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + list = clist_append(addr); + + addr_list = mailimf_address_list_new(list); + /* do the things */ + mailimf_address_list_free(mb_list); + + return 0; +} + +/* display a list of addresses */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_address_list(struct mailimf_address_list * addr_list) +{ + clistiter * cur; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + display_address(addr); + printf("\n"); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-GROUP" +>mailimf_group - named group of mailboxes</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_group { + char * grp_display_name; /* != NULL */ + struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */ +}; + +struct mailimf_group * +mailimf_group_new(char * grp_display_name, + struct mailimf_mailbox_list * grp_mb_list); + +void mailimf_group_free(struct mailimf_group * group); + </PRE +><P +> This is a list of mailboxes tagged with a name. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN502" +></A +><P +><B +>Example 3-6. example of group</B +></P +><PRE +CLASS="PROGRAMLISTING" +> they play music: <steve@morse.foo>, <neal@morse.foo>, + <yngwie@malmsteen.bar>, <michael@romeo.bar>; + </PRE +></DIV +><P +> <B +CLASS="COMMAND" +>grp_display_name</B +> is the name that will be + displayed for this group, + for example '<B +CLASS="COMMAND" +>group_name</B +>' in + '<B +CLASS="COMMAND" +>group_name: address1@domain1, + address2@domain2;</B +>'. + This must be allocated with malloc(). + <B +CLASS="COMMAND" +>grp_mb_list</B +> is a list of mailboxes + (see <A +HREF="x425.htm#MAILIMF-MAILBOX-LIST" +>the Section called <I +>mailimf_mailbox_list - list of mailboxes</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_group_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_group_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN515" +></A +><P +><B +>Example 3-7. creation and display of a group</B +></P +><PRE +CLASS="PROGRAMLISTING" +>/* creates an empty group */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_group * g; + char * display_name; + + display_name = strdup("undisclosed-recipient"); + g = mailimf_group_new(display_name, NULL); + /* do the things */ + mailimf_group_free(g); +} + +/* creates a group with two mailboxes */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_group * g; + char * display_name; + struct mailimf_mailbox_list * mb_list; + struct mailimf_mailbox * mb; + clist * list; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + list = clist_append(mb); + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + list = clist_append(mb); + + mb_list = mailimf_mailbox_list_new(list); + + display_name = strdup("my_group"); + g = mailimf_group_new(display_name, mb_list); + /* do the things */ + mailimf_group_free(g); + + return 0; +} + +/* display content of group */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_group(struct mailimf_group * group) +{ + printf("name of the group: %s\n", a->group->display_name); + for(cur = clist_begin(a->group->mb_list->list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + display_mailbox(mb); + printf("\n"); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-DATE-TIME" +>mailimf_date_time - date of a message</A +></H2 +><P +>#include <libetpan/libetpan.h> + +struct mailimf_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +struct mailimf_date_time * +mailimf_date_time_new(int dt_day, int dt_month, int dt_year, + int dt_hour, int dt_min, int dt_sec, int dt_zone); + +void mailimf_date_time_free(struct mailimf_date_time * date_time); + </P +><P +> This is the date and time of a message. + For example : + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN522" +></A +><P +><B +>Example 3-8. example of date</B +></P +><PRE +CLASS="PROGRAMLISTING" +>Thu, 11 Dec 2003 00:15:02 +0100. + </PRE +></DIV +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>dt_day</B +> is the day of month (1 to 31) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dt_month</B +> (1 to 12) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dt_year</B +> (4 digits) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dt_hour</B +> (0 to 23) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dt_min</B +> (0 to 59) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dt_sec</B +> (0 to 59) + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>dt_zone</B +> (this is the decimal value that + we can read, for example: for + '<B +CLASS="COMMAND" +>-0200</B +>', the value is + <B +CLASS="COMMAND" +>-200</B +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_date_time_new()</B +> creates and + initializes a date structure with a value. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_date_time_free()</B +> frees memory used + by the structure. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN553" +></A +><P +><B +>Example 3-9. creation and display of date</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_date_time * d; + + d = mailimf_date_time_new(9, 5, 2003, 3, 01, 40, -0200); + /* do the things */ + mailimf_date_time_free(d); + + return 0; +} + +/* display the date */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_date(struct mailimf_date_time * d) +{ + printf("%02i/%02i/%i %02i:%02i:%02i %+04i\n", + d->dt_day, d->dt_month, d->dt_year, + d->dt_hour, d->dt_min, d->dt_sec, d->dt_zone); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-ORIG-DATE" +>mailimf_orig_date - parsed content of date header</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_orig_date { + struct mailimf_date_time * dt_date_time; /* != NULL */ +}; + +struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time * + dt_date_time); + +void mailimf_orig_date_free(struct mailimf_orig_date * orig_date); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Date</B +> or + <B +CLASS="COMMAND" +>Resent-Date</B +>. + It encapsulates a mailimf_date_time + </P +><P +> <B +CLASS="COMMAND" +>dt_date_time</B +> is the parsed date + (see <A +HREF="x425.htm#MAILIMF-DATE-TIME" +>the Section called <I +>mailimf_date_time - date of a message</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_orig_date_new()</B +> creates and + initializes a data structure with + a value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_orig_date_free()</B +> frees memory used + by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN569" +></A +><P +><B +>Example 3-10. creation and display of Date field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_date_time * d; + struct mailimf_orig_date * date; + + d = mailimf_date_time_new(9, 5, 2003, 3, 01, 40, -0200); + date = mailimf_orig_date_new(d); + /* do the things */ + mailimf_orig_date_free(date); + + return 0; +} + +/* display date header */ + +#include <libetpan/libetpan.h> + +void display_orig_date(struct mailimf_orig_date * orig_date) +{ + display_date_time(d->dt_date_time); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-FROM" +>mailimf_from - parsed content of From header</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_from { + struct mailimf_mailbox_list * frm_mb_list; /* != NULL */ +}; + +struct mailimf_from * +mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list); + +void mailimf_from_free(struct mailimf_from * from); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>From</B +> or + <B +CLASS="COMMAND" +>Resent-From</B +>. + </P +><P +> <B +CLASS="COMMAND" +>frm_mb_list</B +> is the parsed mailbox list + (see <A +HREF="x425.htm#MAILIMF-MAILBOX-LIST" +>the Section called <I +>mailimf_mailbox_list - list of mailboxes</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_from_new()</B +> creates and initializes + a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_from_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN585" +></A +><P +><B +>Example 3-11. creation and display of a From header</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + /* do the things */ + mailimf_from_free(from); + + return 0; +} + +/* display content of from header */ + +#include <libetpan/libetpan.h> + +void display_from(struct mailimf_from * from) +{ + display_mailbox_list(from->frm_mb_list); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-SENDER" +>mailimf_sender - parsed content of Sender header</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_sender { + struct mailimf_mailbox * snd_mb; /* != NULL */ +}; + +struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb); + +void mailimf_sender_free(struct mailimf_sender * sender); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Sender</B +> or + <B +CLASS="COMMAND" +>Resent-Sender</B +>. + </P +><P +> <B +CLASS="COMMAND" +>snd_mb</B +> is the parsed mailbox + (see <A +HREF="x425.htm#MAILIMF-MAILBOX" +>the Section called <I +>mailimf_mailbox - mailbox</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_sender_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_sender_free()</B +> This function frees + memory used by the structure and substructures + will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN601" +></A +><P +><B +>Example 3-12. creation and display of Sender field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + + sender = mailimf_sender_new(mb); + /* do the things */ + mailimf_sender_free(sender); + + return 0; +} + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_sender(struct mailimf_sender * sender) +{ + display_mailbox(sender->snd_mb); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-REPLY-TO" +>mailimf_reply_to - parsed content of Reply-To header</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_reply_to { + struct mailimf_address_list * rt_addr_list; /* != NULL */ +}; + +struct mailimf_reply_to * +mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list); + +void mailimf_reply_to_free(struct mailimf_reply_to * reply_to); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Reply-To</B +>. + </P +><P +> <B +CLASS="COMMAND" +>addr_list</B +> is the parsed address list + (see <A +HREF="x425.htm#MAILIMF-ADDRESS-LIST" +>the Section called <I +>mailimf_address_list - list of addresses</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_reply_to_new()</B +> creates and + initializes a data structure with a value. Structures given + as argument are referenced by the created object and will be + freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_reply_to_free()</B +> frees memory used + by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN616" +></A +><P +><B +>Example 3-13. creation and display of Reply-To field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_reply_to * reply_to; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + reply_to = mailimf_reply_to_new(addr_list); + /* do the things */ + mailimf_reply_to_free(reply_to); + + return 0; +} + +/* display Reply-To header */ + +#include <libetpan/libetpan.h> + +void display_reply_to(struct mailimf_reply_to * reply_to) +{ + display_address_list(reply_to->addr_list); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-TO" +>mailimf_to - parsed content of To header</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +> struct mailimf_to { + struct mailimf_address_list * to_addr_list; /* != NULL */ +}; + +struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list); + +void mailimf_to_free(struct mailimf_to * to); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>To</B +> or + <B +CLASS="COMMAND" +>Resent-To</B +>. + </P +><P +> <B +CLASS="COMMAND" +>to_addr_list</B +> is the parsed address list + (see <A +HREF="x425.htm#MAILIMF-ADDRESS-LIST" +>the Section called <I +>mailimf_address_list - list of addresses</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_to_new()</B +> creates and initializes a + data structure with a value. Structures given as argument + are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_to_free()</B +> frees memory used by the + structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN632" +></A +><P +><B +>Example 3-14. creation and display of To field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + /* do the things */ + mailimf_to_free(to); + + return 0; +} + +/* display To header */ + +#include <libetpan/libetpan.h> + +void display_to(struct mailimf_to * to) +{ + display_address_list(to->to_addr_list); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-CC" +>mailimf_cc - parsed content of Cc</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_cc { + struct mailimf_address_list * cc_addr_list; /* != NULL */ +}; + +struct mailimf_cc * +mailimf_cc_new(struct mailimf_address_list * cc_addr_list); + +void mailimf_cc_free(struct mailimf_cc * cc);</PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Cc</B +> or + <B +CLASS="COMMAND" +>Resent-Cc</B +>. + </P +><P +> <B +CLASS="COMMAND" +>cc_addr_list</B +> is the parsed address list + (see <A +HREF="x425.htm#MAILIMF-ADDRESS-LIST" +>the Section called <I +>mailimf_address_list - list of addresses</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_cc_new()</B +> creates and initializes a + data structure with a value. Structures given as argument + are referenced by the created object and will be freed if + the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_cc_free()</B +> This function frees + memory used by the structure and substructures will also be + released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN648" +></A +><P +><B +>Example 3-15. creation and display of Cc field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + cc = mailimf_cc_new(addr_list); + /* do the things */ + mailimf_cc_free(cc); + + return 0; +} + +/* display content of Cc field */ + +#include <libetpan/libetpan.h> + +void display_cc(struct mailimf_cc * cc) +{ + display_address_list(cc->cc_addr_list); +} + + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-BCC" +>mailimf_bcc - parsed content of Bcc field</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_bcc { + struct mailimf_address_list * bcc_addr_list; /* can be NULL */ +}; + +struct mailimf_bcc * +mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list); + +void mailimf_bcc_free(struct mailimf_bcc * bcc); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Bcc</B +> or + <B +CLASS="COMMAND" +>Resent-Bcc</B +>. + </P +><P +> <B +CLASS="COMMAND" +>bcc_addr_list</B +> is the parsed address list + (see <A +HREF="x425.htm#MAILIMF-ADDRESS-LIST" +>the Section called <I +>mailimf_address_list - list of addresses</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_bcc_new()</B +> creates and initializes a + data structure with a value. Structures given as argument + are referenced by the created object and will be freed if + the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_bcc_free()</B +> frees memory used by the + structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN664" +></A +><P +><B +>Example 3-16. creation and display of Bcc field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>/* create visible Bcc */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + clist * list; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + + list = clist_new(); + + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + mb = mailimf_mailbox_new(strdup("Christophe GIAUME"), + strdup("christophe@giaume.com")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + + addr_list = mailimf_address_list_new(list); + + bcc = mailimf_bcc_new(addr_list); + /* do the things */ + mailimf_bcc_free(bcc); + + return 0; +} + +/* create unvisible Bcc */ + +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_bcc * bcc; + + bcc = mailimf_bcc_new(NULL); + /* do the things */ + mailimf_bcc_free(bcc); + + return 0; +} + +/* display content of Bcc field */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_bcc(struct mailimf_bcc * bcc) +{ + if (bcc->addr_list == NULL) { + printf("hidden Bcc\n"); + } + else { + display_address_list(bcc->bcc_addr_list); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-MESSAGE-ID" +>mailimf_message_id - parsed content of Message-ID header</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_message_id { + char * mid_value; /* != NULL */ +}; + +struct mailimf_message_id * mailimf_message_id_new(char * mid_value); + +void mailimf_message_id_free(struct mailimf_message_id * message_id); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Message-ID</B +> + or <B +CLASS="COMMAND" +>Resent-Message-ID</B +>. For example : + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN673" +></A +><P +><B +>Example 3-17. example of Message-ID</B +></P +><PRE +CLASS="PROGRAMLISTING" +>Message-ID: <200312100009.43592@c01n-c01n.plop.P4N>> + </PRE +></DIV +><P +> <B +CLASS="COMMAND" +>mid_value</B +> is the message identifier. + It is not enclosed by angle bracket. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_message_id_new()</B +> This function + creates and initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> The given string is allocated with + <B +CLASS="COMMAND" +>malloc()</B +> and is not enclosed by angle bracket. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_message_id_free()</B +> frees memory + used by the structure and substructures will also be + released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN684" +></A +><P +><B +>Example 3-18. creation and display of Message-ID field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_message_id * msg_id; + char * id; + + id = strdup("1037197913.3dd26259752fa@imp.free.fr"); + msg_id = mailimf_message_id_new(id); + /* do the things */ + mailimf_message_id_free(msg_id); + + return 0; +} + +/* display message id */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_message_id(struct mailimf_message_id * msg_id) +{ + printf("%s\n", msg_id->mid_value); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-IN-REPLY-TO" +>mailimf_in_reply_to - parsed content of In-Reply-To + field</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_in_reply_to { + clist * mid_list; /* list of (char *), != NULL */ +}; + +struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list); + +void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to); + </PRE +><P +> content of a header <B +CLASS="COMMAND" +>In-Reply-To</B +>. + For example : + </P +><PRE +CLASS="PROGRAMLISTING" +>In-Reply-To: <etPan.3fd5fa29.4c3901c1.6b39@homer> + </PRE +><P +> <B +CLASS="COMMAND" +>mid_list</B +> is a <B +CLASS="COMMAND" +>clist</B +> + in which elements are message identifiers. + their types are <B +CLASS="COMMAND" +>(char *)</B +> and they are + allocated with <B +CLASS="COMMAND" +>malloc()</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_in_reply_to_new()</B +> creates and + initializes a data structure with a value. Structures given + as argument are referenced by the created object and will be + freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_in_reply_to_free()</B +> frees memory + used by the structure and substructures will also be + released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN702" +></A +><P +><B +>Example 3-19. creation and display of In-Reply-To field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_in_reply_to * in_reply_to; + clist * msg_id_list; + + msg_id_list = clist_new(); + clist_append(msg_id_list, + strdup("etPan.3ebbcc18.4014197f.bc1@homer.invalid")); + + in_reply_to = mailimf_in_reply_to_new(msg_id_list); + /* do the things */ + mailimf_in_reply_to_free(in_reply_to); + + return 0; +} + +/* display the content of mailimf_in_reply_to */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_in_reply_to(struct mailimf_in_reply_to * in_reply_to) +{ + clistiter * cur; + + for(cur = clist_begin(in_reply_to->mid_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * str; + + str = clist_content(cur); + + printf("%s\n", str); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-REFERENCES" +>mailimf_references - parsed content of References field</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_references { + clist * mid_list; /* list of (char *) */ + /* != NULL */ +}; + +struct mailimf_references * mailimf_references_new(clist * mid_list); + +void mailimf_references_free(struct mailimf_references * references); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>References</B +>. + For example : + </P +><PRE +CLASS="PROGRAMLISTING" +>In-Reply-To: <etPan.3fd5fa29.4c3901c1.6b39@homer> + <3FD5FA78.A1D98E7@oleane.net> + <etPan.3fd5fc69.2b349482.730e@homer> + </PRE +><P +> <B +CLASS="COMMAND" +>mid_list</B +> is a <B +CLASS="COMMAND" +>clist</B +> + in which elements are message identifiers. + their types are <B +CLASS="COMMAND" +>(char *)</B +> and they are + allocated with <B +CLASS="COMMAND" +>malloc()</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_references_new()</B +> creates and + initializes a data structure with a value. Structures given + as argument are referenced by the created object and will be + freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_references_free()</B +> frees memory + used by the structure and substructures will also be + released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN720" +></A +><P +><B +>Example 3-20. creation and display of References field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_references * ref; + clist * msg_id_list; + + msg_id_list = clist_new(); + clist_append(msg_id_list, + strdup("200304280144.23633.wim.delvaux@adaptiveplanet.com")); + clist_append(msg_id_list, + strdup("200304301153.19688.wim.delvaux@adaptiveplanet.com")); + clist_append(msg_id_list, + strdup("etPan.3eb29de4.5fc4d652.3f83@homer")); + + ref = mailimf_references_new(msg_id_list); + /* do the things */ + mailimf_in_reply_to_free(ref); + + return 0; +} + +/* display references */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_references(struct mailimf_references * ref) +{ + clistiter * cur; + + for(cur = clist_begin(ref->mid_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * msg_id; + + msg_id = clist_content(cur); + + printf("%s\n", msg_id); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-SUBJECT" +>mailimf_subject - parsed content of Subject field</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_subject { + char * sbj_value; /* != NULL */ +}; + +struct mailimf_subject * mailimf_subject_new(char * sbj_value); + +void mailimf_subject_free(struct mailimf_subject * subject);</PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Subject</B +>. + </P +><P +> <B +CLASS="COMMAND" +>sbj_value</B +> is the value of the field. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_subject_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_subject_free</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN734" +></A +><P +><B +>Example 3-21. creation and display of Subject field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_subject * subject; + + subject = mailimf_subject_new(strdup("example of subject")); + /* do the things */ + mailimf_subject_free(subject); + + return 0; +} + +/* display subject header */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_subject(struct mailimf_subject * subject) +{ + printf("%s\n", subject->value); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-COMMENTS" +>mailimf_comments - parsed content of Comments field</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_comments { + char * cm_value; /* != NULL */ +}; + +struct mailimf_comments * mailimf_comments_new(char * cm_value); + +void mailimf_comments_free(struct mailimf_comments * comments); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Comments</B +>. + </P +><P +> <B +CLASS="COMMAND" +>cm_value</B +> is the value of the field. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_comments_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_comments_free()</B +> frees memory used + by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN748" +></A +><P +><B +>Example 3-22. creation and display of Comment field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_comments * comments; + + comments = mailimf_comments_new(strdup("example of comment")); + /* do the things */ + mailimf_comments_free(comments); + + return 0; +} + +/* display the content of a comments */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_comments(struct mailimf_comments * comments) +{ + printf("%s\n", comments->cm_value); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-KEYWORDS" +>mailimf_keywords - parsed content of Keywords field</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_keywords { + clist * kw_list; /* list of (char *), != NULL */ +}; + +struct mailimf_keywords * mailimf_keywords_new(clist * kw_list); + +void mailimf_keywords_free(struct mailimf_keywords * keywords); + </PRE +><P +> This is the content of a header <B +CLASS="COMMAND" +>Keywords</B +>. + </P +><P +> <B +CLASS="COMMAND" +>kw_list</B +> is the list of keywords. This is + a list of <B +CLASS="COMMAND" +>(char *)</B +> allocated with malloc(). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_keywords_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_keywords_free()</B +> frees memory used + by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN763" +></A +><P +><B +>Example 3-23. creation and display of Keywords field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_keywords * keywords; + clist * list; + + list = clist_new(); + clist_append(list, strdup("sauerkraut")); + clist_append(list, strdup("potatoes")); + clist_append(list, strdup("cooking")); + + keywords = mailimf_keywords_new(list); + /* do the things */ + mailimf_keywords_free(keywords); + + return 0; +} + +/* display the content of mailimf_in_reply_to */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_keywords(struct mailimf_keywords * kw) +{ + clistiter * cur; + + for(cur = clist_begin(kw->kw_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * str; + + str = clist_content(cur); + + printf("%s\n", str); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-RETURN" +>mailimf_return - parsed content of Return-Path field</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_return { + struct mailimf_path * ret_path; /* != NULL */ +}; + +struct mailimf_return * +mailimf_return_new(struct mailimf_path * ret_path); + +void mailimf_return_free(struct mailimf_return * return_path); + </PRE +><P +> This is the content of a header + <B +CLASS="COMMAND" +>Return-Path</B +>. + </P +><P +> <B +CLASS="COMMAND" +>ret_path</B +> is the parsed value of Return-Path + (see <A +HREF="x425.htm#MAILIMF-PATH" +>the Section called <I +>mailimf_path - address in Return-Path field</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_return_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_return_free()</B +> frees memory used + by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN778" +></A +><P +><B +>Example 3-24. creation and display of Return-Path field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_path * path; + struct mailimf_return * r; + + path = mailimf_path_new(strdup("dinh.viet.hoa@free.fr")); + r = mailimf_return_new(path); + /* do the things */ + mailimf_return_free(r); + + return 0; +} + +/* display return path */ + +#include <libetpan/libetpan.h> + +void display_return(struct mailimf_return * r) +{ + display_path(r->ret_path); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-PATH" +>mailimf_path - address in Return-Path field</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_path { + char * pt_addr_spec; /* can be NULL */ +}; + +struct mailimf_path * mailimf_path_new(char * pt_addr_spec); + +void mailimf_path_free(struct mailimf_path * path); + </PRE +><P +> This is the encapsulation of address specifier for + <B +CLASS="COMMAND" +>Return-Path</B +> content. + </P +><P +> <B +CLASS="COMMAND" +>pt_addr_spec</B +> is a mailbox destination. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_path_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> The given string is allocated with + <B +CLASS="COMMAND" +>malloc()</B +>. This is a address + specifier. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_path_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN794" +></A +><P +><B +>Example 3-25. Creation and display of return path</B +></P +><PRE +CLASS="PROGRAMLISTING" +> +#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_path * path; + + path = mailimf_path_new(strdup("dinh.viet.hoa@free.fr")); + /* do the things */ + mailimf_path_free(r); + + return 0; +} + +/* display return path */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_path(struct mailimf_path * path) +{ + printf("%s\n", path->pt_addr_spec); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-OPTIONAL-FIELD" +>mailimf_optional_field - non-standard header</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_optional_field { + char * fld_name; /* != NULL */ + char * fld_value; /* != NULL */ +}; + +struct mailimf_optional_field * +mailimf_optional_field_new(char * fld_name, char * fld_value); + +void mailimf_optional_field_free(struct mailimf_optional_field * opt_field); + </PRE +><P +> This is a non-standard header or unparsed header. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fld_name</B +> is the name of the header + field. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_value</B +> is the value of the header + field. + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_optional_field_new()</B +> This + function creates and initializes a data structure with a + value. Structures given as argument are referenced by the + created object and will be freed if the object is released. + </P +><P +> field name and field value have to be allocated with + <B +CLASS="COMMAND" +>malloc()</B +>. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_optional_field_free()</B +> This + function frees memory used by the structure and + substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN814" +></A +><P +><B +>Example 3-26. creation and display of non-standard fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_optional_field * opt; + + opt = mailimf_optional_field_new(strdup("X-My-Field"), strdup("my value")); + /* do the things */ + mailimf_optional_field_free(opt); + + return 0; +} + +/* display the optional field */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_optional_field(struct mailimf_optional_field * opt) +{ + printf("%s: %s\n", opt->fld_name, opt->fld_value); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-FIELD" +>mailimf_field - header field</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +enum { + MAILIMF_FIELD_NONE, /* on parse error */ + MAILIMF_FIELD_RETURN_PATH, /* Return-Path */ + MAILIMF_FIELD_RESENT_DATE, /* Resent-Date */ + MAILIMF_FIELD_RESENT_FROM, /* Resent-From */ + MAILIMF_FIELD_RESENT_SENDER, /* Resent-Sender */ + MAILIMF_FIELD_RESENT_TO, /* Resent-To */ + MAILIMF_FIELD_RESENT_CC, /* Resent-Cc */ + MAILIMF_FIELD_RESENT_BCC, /* Resent-Bcc */ + MAILIMF_FIELD_RESENT_MSG_ID, /* Resent-Message-ID */ + MAILIMF_FIELD_ORIG_DATE, /* Date */ + MAILIMF_FIELD_FROM, /* From */ + MAILIMF_FIELD_SENDER, /* Sender */ + MAILIMF_FIELD_REPLY_TO, /* Reply-To */ + MAILIMF_FIELD_TO, /* To */ + MAILIMF_FIELD_CC, /* Cc */ + MAILIMF_FIELD_BCC, /* Bcc */ + MAILIMF_FIELD_MESSAGE_ID, /* Message-ID */ + MAILIMF_FIELD_IN_REPLY_TO, /* In-Reply-To */ + MAILIMF_FIELD_REFERENCES, /* References */ + MAILIMF_FIELD_SUBJECT, /* Subject */ + MAILIMF_FIELD_COMMENTS, /* Comments */ + MAILIMF_FIELD_KEYWORDS, /* Keywords */ + MAILIMF_FIELD_OPTIONAL_FIELD, /* other field */ +}; + +struct mailimf_field { + int fld_type; + union { + struct mailimf_return * fld_return_path; /* can be NULL */ + struct mailimf_orig_date * fld_resent_date; /* can be NULL */ + struct mailimf_from * fld_resent_from; /* can be NULL */ + struct mailimf_sender * fld_resent_sender; /* can be NULL */ + struct mailimf_to * fld_resent_to; /* can be NULL */ + struct mailimf_cc * fld_resent_cc; /* can be NULL */ + struct mailimf_bcc * fld_resent_bcc; /* can be NULL */ + struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */ + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ + struct mailimf_optional_field * fld_optional_field; /* can be NULL */ + } fld_data; +}; + +struct mailimf_field * +mailimf_field_new(int fld_type, + struct mailimf_return * fld_return_path, + struct mailimf_orig_date * fld_resent_date, + struct mailimf_from * fld_resent_from, + struct mailimf_sender * fld_resent_sender, + struct mailimf_to * fld_resent_to, + struct mailimf_cc * fld_resent_cc, + struct mailimf_bcc * fld_resent_bcc, + struct mailimf_message_id * fld_resent_msg_id, + struct mailimf_orig_date * fld_orig_date, + struct mailimf_from * fld_from, + struct mailimf_sender * fld_sender, + struct mailimf_reply_to * fld_reply_to, + struct mailimf_to * fld_to, + struct mailimf_cc * fld_cc, + struct mailimf_bcc * fld_bcc, + struct mailimf_message_id * fld_message_id, + struct mailimf_in_reply_to * fld_in_reply_to, + struct mailimf_references * fld_references, + struct mailimf_subject * fld_subject, + struct mailimf_comments * fld_comments, + struct mailimf_keywords * fld_keywords, + struct mailimf_optional_field * fld_optional_field); + +void mailimf_field_free(struct mailimf_field * field); + </PRE +><P +> This is one header field of a message. + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>type</B +> is the type of the field. This define the + type of the field. + Only the corresponding field should be, then, + filled. The value of this field can be one of : + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RETURN_PATH</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_DATE</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_FROM</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_SENDER</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_TO</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_CC</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_BCC</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_MSG_ID</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_ORIG_DATE</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_FROM</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_SENDER</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_REPLY_TO</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_TO</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_CC</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_BCC</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_MESSAGE_ID</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_IN_REPLY_TO</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_REFERENCES</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_SUBJECT</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_COMMENTS</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_KEYWORDS</B +>, + <B +CLASS="COMMAND" +>MAILIMF_FIELD_OPTIONAL_FIELD</B +>. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_return_path</B +> is the + parsed content of the Return-Path field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_RETURN_PATH</B +> + (see <A +HREF="x425.htm#MAILIMF-RETURN" +>the Section called <I +>mailimf_return - parsed content of Return-Path field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_resent_date</B +> is the + parsed content of the Resent-Date field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_DATE</B +> + (see <A +HREF="x425.htm#MAILIMF-ORIG-DATE" +>the Section called <I +>mailimf_orig_date - parsed content of date header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_resent_from</B +> is the + parsed content of the Resent-From field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_FROM</B +> + (see <A +HREF="x425.htm#MAILIMF-FROM" +>the Section called <I +>mailimf_from - parsed content of From header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_resent_sender</B +> is the + parsed content of the Resent-Sender field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_SENDER</B +> + (see <A +HREF="x425.htm#MAILIMF-SENDER" +>the Section called <I +>mailimf_sender - parsed content of Sender header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_resent_to</B +> is the parsed + content of the Resent-To field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_TO</B +> + (see <A +HREF="x425.htm#MAILIMF-TO" +>the Section called <I +>mailimf_to - parsed content of To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_resent_cc</B +> is the parsed + content of the Resent-Cc field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_CC</B +> + (see <A +HREF="x425.htm#MAILIMF-CC" +>the Section called <I +>mailimf_cc - parsed content of Cc</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_resent_bcc</B +> is the parsed + content of the Resent-Bcc field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_BCC</B +> + (see <A +HREF="x425.htm#MAILIMF-BCC" +>the Section called <I +>mailimf_bcc - parsed content of Bcc field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_resent_msg_id</B +> is the + parsed content of the Resent-Message-ID field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_RESENT_MSG_ID</B +> + (see <A +HREF="x425.htm#MAILIMF-MESSAGE-ID" +>the Section called <I +>mailimf_message_id - parsed content of Message-ID header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_orig_date</B +> is the parsed + content of the Date field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_ORIG_DATE</B +> + (see <A +HREF="x425.htm#MAILIMF-ORIG-DATE" +>the Section called <I +>mailimf_orig_date - parsed content of date header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_from</B +> is the parsed + content of the From field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_FROM</B +> + (see <A +HREF="x425.htm#MAILIMF-FROM" +>the Section called <I +>mailimf_from - parsed content of From header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_sender</B +> is the parsed + content of the Sender field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_SENDER</B +> + (see <A +HREF="x425.htm#MAILIMF-SENDER" +>the Section called <I +>mailimf_sender - parsed content of Sender header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_reply_to</B +> is the parsed + content of the Reply-To field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_REPLY_TO</B +> + (see <A +HREF="x425.htm#MAILIMF-REPLY-TO" +>the Section called <I +>mailimf_reply_to - parsed content of Reply-To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_to</B +> is the parsed content + of the To field if type is + <B +CLASS="COMMAND" +>MAILIMF_FIELD_TO</B +> + (see <A +HREF="x425.htm#MAILIMF-TO" +>the Section called <I +>mailimf_to - parsed content of To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_cc</B +> is the parsed content + of the Cc field if type is + <B +CLASS="COMMAND" +>MAILIMF_FIELD_CC</B +> + (see <A +HREF="x425.htm#MAILIMF-CC" +>the Section called <I +>mailimf_cc - parsed content of Cc</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_bcc</B +> is the parsed + content of the Bcc field if type is + <B +CLASS="COMMAND" +>MAILIMF_FIELD_BCC</B +> + (see <A +HREF="x425.htm#MAILIMF-BCC" +>the Section called <I +>mailimf_bcc - parsed content of Bcc field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_message_id</B +> is the parsed + content of the Message-ID field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_MESSAGE_ID</B +> + (see <A +HREF="x425.htm#MAILIMF-MESSAGE-ID" +>the Section called <I +>mailimf_message_id - parsed content of Message-ID header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_in_reply_to</B +> is the + parsed content of the In-Reply-To field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_IN_REPLY_TO</B +> + (see <A +HREF="x425.htm#MAILIMF-IN-REPLY-TO" +>the Section called <I +>mailimf_in_reply_to - parsed content of In-Reply-To + field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_references</B +> is the parsed + content of the References field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_REFERENCES</B +> + (see <A +HREF="x425.htm#MAILIMF-REFERENCES" +>the Section called <I +>mailimf_references - parsed content of References field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_subject</B +> is the content + of the Subject field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_SUBJECT</B +> + (see <A +HREF="x425.htm#MAILIMF-SUBJECT" +>the Section called <I +>mailimf_subject - parsed content of Subject field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_comments</B +> is the content of the + Comments field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_COMMENTS</B +> + (see <A +HREF="x425.htm#MAILIMF-COMMENTS" +>the Section called <I +>mailimf_comments - parsed content of Comments field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_keywords</B +> is the parsed + content of the Keywords field + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_KEYWORDS</B +> + (see <A +HREF="x425.htm#MAILIMF-KEYWORDS" +>the Section called <I +>mailimf_keywords - parsed content of Keywords field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_data.fld_optional_field</B +> is an + other field and is not parsed + if type is <B +CLASS="COMMAND" +>MAILIMF_FIELD_OPTIONAL_FIELD</B +> + (see <A +HREF="x425.htm#MAILIMF-OPTIONAL-FIELD" +>the Section called <I +>mailimf_optional_field - non-standard header</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_field_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_field_free()</B +> frees memory used by + the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN961" +></A +><P +><B +>Example 3-27. creation and display of field</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_field * f; + struct mailimf_mailbox * mb; + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + /* do the things */ + mailimf_field_free(f); + + return 0; +} + +/* display content of the header */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_field(struct mailimf_field * field) +{ + switch (field->type) { + case MAILIMF_FIELD_RETURN_PATH: + printf("Return-Path:\n"); + display_return(field->fld_data.fld_return_path); + break; + case MAILIMF_FIELD_RESENT_DATE: + printf("Resent-Date:\n"); + display_orig_date(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_RESENT_FROM: + printf("Resent-From:\n"); + display_from(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_RESENT_SENDER: + printf("Resent-Sender:\n"); + display_sender(field->fld_data.fld_resent_sender); + break; + case MAILIMF_FIELD_RESENT_TO: + printf("Resent-To:\n"); + display_to(field->fld_data.fld_resent_to); + break; + case MAILIMF_FIELD_RESENT_CC: + printf("Resent-Cc:\n"); + display_from(field->fld_data.fld_resent_cc); + break; + case MAILIMF_FIELD_RESENT_BCC: + printf("Resent-Bcc:\n"); + display_from(field->fld_data.fld_resent_bcc); + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + printf("Resent-Message-ID:\n"); + display_message_id(field->fld_data.fld_resent_msg_id); + break; + case MAILIMF_FIELD_ORIG_DATE: + printf("Date:\n"); + display_orig_date(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + printf("From:\n"); + display_from(field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + printf("Sender:\n"); + display_sender(field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + printf("Reply-To:\n"); + display_reply_to(field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + printf("To:\n"); + display_to(field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + printf("Cc:\n"); + display_cc(field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + printf("Bcc:\n"); + display_bcc(field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + printf("Message-ID:\n"); + display_message_id(field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + printf("In-Reply-To:\n"); + display_in_reply_to(field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + printf("References:\n"); + display_references(field->fld_data.fld_references_to); + break; + case MAILIMF_FIELD_SUBJECT: + printf("Subject:\n"); + display_subject(field->fld_data.fld_subject); + break; + case MAILIMF_FIELD_COMMENTS: + printf("Comments:\n"); + display_comments(field->fld_data.fld_comments); + break; + case MAILIMF_FIELD_KEYWORDS: + printf("Keywords:\n"); + display_keywords(field->fld_data.fld_keywords); + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + printf("[optional field]:\n"); + display_optional_field(field->fld_data.fld_optional_field); + break; + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-FIELDS" +>mailimf_fields - list of header fields</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_fields { + clist * fld_list; /* list of (struct mailimf_field *), != NULL */ +}; + +struct mailimf_fields * mailimf_fields_new(clist * fld_list); + +void mailimf_fields_free(struct mailimf_fields * fields); + </PRE +><P +> This is the list of header fields of a message. + </P +><P +> <B +CLASS="COMMAND" +>fld_list</B +> is a list of header fields. This + is a <B +CLASS="COMMAND" +>clist</B +> which elements are + of type <B +CLASS="COMMAND" +>mailimf_field</B +> (see <A +HREF="x425.htm#MAILIMF-FIELD" +>the Section called <I +>mailimf_field - header field</I +></A +>). + </P +><P +> <B +CLASS="COMMAND" +>mailimf_fields_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_fields_free()</B +> frees memory used + by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN977" +></A +><P +><B +>Example 3-28. creation and display of header fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + struct mailimf_field * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + /* do the things */ + mailimf_fields_free(fields); + + return 0; +} + +/* display list of headers */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_fields(struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(field->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_field * f; + + f = clist_content(cur); + + display_field(f); + printf("\n"); + } +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-BODY" +>mailimf_body - message body without headers</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_body { + const char * bd_text; /* != NULL */ + size_t bd_size; +}; + +struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size); + +void mailimf_body_free(struct mailimf_body * body); + </PRE +><P +> This is the text content of a message (without headers). + </P +><P +> <P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>bd_text</B +> is the beginning of the + text part, it is a substring of an other string. + It is not necessarily zero terminated. + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>bd_size</B +> is the size of the text part + </P +></LI +></UL +> + </P +><P +> <B +CLASS="COMMAND" +>mailimf_body_new()</B +> creates and + initializes a data structure with a value. + Text given as argument will <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> be released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_body_free()</B +> frees memory used by + the structure. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN997" +></A +><P +><B +>Example 3-29. creation and display of message body</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_body * b; + + b = mailimf_body_new("this is the content of the message", 34); + /* do the things */ + mailimf_body_free(b); + + return 0; +} + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_body(struct mailimf_body * b) +{ + char * text; + + text = malloc(b->size + 1); + strncpy(text, b->bd_text, b->bd_size); + text[b->size] = 0; + + puts(text); + printf("\n"); + + free(text); + + return 0; +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-MESSAGE" +>mailimf_message - parsed message</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_message { + struct mailimf_fields * msg_fields; /* != NULL */ + struct mailimf_body * msg_body; /* != NULL */ +}; + +struct mailimf_message * +mailimf_message_new(struct mailimf_fields * msg_fields, + struct mailimf_body * msg_body); + +void mailimf_message_free(struct mailimf_message * message); + </PRE +><P +> This is the message content (text and headers). + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>msg_fields</B +> is the header fields of + the message + (see <A +HREF="x425.htm#MAILIMF-FIELDS" +>the Section called <I +>mailimf_fields - list of header fields</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>msg_body</B +> is the text part of the message + (see <A +HREF="x425.htm#MAILIMF-BODY" +>the Section called <I +>mailimf_body - message body without headers</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_message_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will be freed if the object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_message_free()</B +> frees memory used + by the structure and substructures will also be released. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1017" +></A +><P +><B +>Example 3-30. creation and display of message</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_body * b; + struct mailimf_message * m; + struct mailimf_fields * fields; + struct mailimf_fields * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build text content */ + + b = mailimf_body_new("this is the content of the message", 34); + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + + /* build message */ + + m = mailimf_message_new(fields, b); + /* do the things */ + mailimf_message_free(m); + + return 0; +} + +/* display the message */ + +#include <libetpan/libetpan.h> +#include <stdio.h> + +void display_message(struct mailimf_message * msg) +{ + display_fields(msg->msg_fields); + printf("\n"); + display_body(msg->msg_body); + printf("\n"); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAILIMF-SINGLE-FIELDS" +>mailimf_single_fields - simplified fields</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +struct mailimf_single_fields { + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ +}; + +struct mailimf_single_fields * +mailimf_single_fields_new(struct mailimf_fields * fields); + +void mailimf_single_fields_free(struct mailimf_single_fields * + single_fields); + +void mailimf_single_fields_init(struct mailimf_single_fields * single_fields, + struct mailimf_fields * fields);</PRE +><P +> Structure that contains some standard fields and allows access + to a given header without running through the list. + </P +><P +> mailimf_fields is the native structure that IMF module will use, + this module will provide an easier structure to use when + parsing fields. + mailimf_single_fields is an easier structure to get parsed fields, + rather than iteration over the list of fields + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>fld_orig_date</B +> is the parsed "Date" + field + (see <A +HREF="x425.htm#MAILIMF-ORIG-DATE" +>the Section called <I +>mailimf_orig_date - parsed content of date header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_from</B +> is the parsed "From" field + (see <A +HREF="x425.htm#MAILIMF-FROM" +>the Section called <I +>mailimf_from - parsed content of From header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_sender</B +> is the parsed "Sender "field + (see <A +HREF="x425.htm#MAILIMF-SENDER" +>the Section called <I +>mailimf_sender - parsed content of Sender header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>reply_to</B +> is the parsed "Reply-To" field + (see <A +HREF="x425.htm#MAILIMF-REPLY-TO" +>the Section called <I +>mailimf_reply_to - parsed content of Reply-To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_to</B +> is the parsed "To" field + (see <A +HREF="x425.htm#MAILIMF-TO" +>the Section called <I +>mailimf_to - parsed content of To header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_cc</B +> is the parsed "Cc" field + (see <A +HREF="x425.htm#MAILIMF-CC" +>the Section called <I +>mailimf_cc - parsed content of Cc</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_bcc</B +> is the parsed "Bcc" field + (see <A +HREF="x425.htm#MAILIMF-BCC" +>the Section called <I +>mailimf_bcc - parsed content of Bcc field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_message_id</B +> is the parsed + "Message-ID" field. + (see <A +HREF="x425.htm#MAILIMF-MESSAGE-ID" +>the Section called <I +>mailimf_message_id - parsed content of Message-ID header</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_in_reply_to</B +> is the parsed + "In-Reply-To" field. + (see <A +HREF="x425.htm#MAILIMF-IN-REPLY-TO" +>the Section called <I +>mailimf_in_reply_to - parsed content of In-Reply-To + field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_references</B +> is the parsed + "References" field. + (see <A +HREF="x425.htm#MAILIMF-REFERENCES" +>the Section called <I +>mailimf_references - parsed content of References field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_subject</B +> is the parsed "Subject" field + (see <A +HREF="x425.htm#MAILIMF-SUBJECT" +>the Section called <I +>mailimf_subject - parsed content of Subject field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_comments</B +> is the parsed "Comments" field + (see <A +HREF="x425.htm#MAILIMF-COMMENTS" +>the Section called <I +>mailimf_comments - parsed content of Comments field</I +></A +>). + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>fld_keywords</B +> is the parsed "Keywords" field + (see <A +HREF="x425.htm#MAILIMF-KEYWORDS" +>the Section called <I +>mailimf_keywords - parsed content of Keywords field</I +></A +>). + </P +></LI +></UL +><P +> <B +CLASS="COMMAND" +>mailimf_single_fields_new()</B +> creates and + initializes a data structure with a value. + Structures given as argument are referenced by the created + object and will <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> be freed if the + object is released. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_single_fields_free()</B +> frees memory + used by the structure and + substructures will <SPAN +CLASS="emphasis" +><I +CLASS="EMPHASIS" +>NOT</I +></SPAN +> be + released. They should be released by the application. + </P +><P +> <B +CLASS="COMMAND" +>mailimf_single_fields_init()</B +> will + initialize fill the data structure, using + the given argument (<B +CLASS="COMMAND" +>fields</B +>). The + interesting fields will be filled into + <B +CLASS="COMMAND" +>single_fields</B +>. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1088" +></A +><P +><B +>Example 3-31. using mailimf_single_fields</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_single_fields * single_fields; + struct mailimf_fields * fields; + struct mailimf_field * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + + /* create the single fields */ + single_fields = mailimf_single_fields_new(fields); + /* do the things */ + mailimf_single_fields_free(single_fields); + mailimf_fields_free(fields); + + return 0; +} + </PRE +></DIV +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN1091" +></A +><P +><B +>Example 3-32. using mailimf_single_fields without memory allocation</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(int argc, char ** argv) +{ + struct mailimf_single_fields single_fields; + struct mailimf_fields * fields; + struct mailimf_field * f; + clist * list; + struct mailimf_from * from; + struct mailimf_to * to + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + struct mailimf_mailbox_list * mb_list; + struct mailimf_address_list * addr_list; + clist * fields_list; + + /* build headers */ + + fields_list = clist_new(); + + /* build header 'From' */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + clist_append(list, mb); + mb_list = mailimf_mailbox_list_new(list); + + from = mailimf_from_new(mb_list); + + f = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + from, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + /* build header To */ + + list = clist_new(); + mb = mailimf_mailbox_new(strdup("DINH =?iso-8859-1?Q?Vi=EAt_Ho=E0?="), + strdup("dinh.viet.hoa@free.fr")); + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + clist_append(list, addr); + addr_list = mailimf_address_list_new(list); + + to = mailimf_to_new(addr_list); + + f = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + + clist_append(fields_list, f); + + fields = mailimf_fields_new(fields_list); + + /* fill the single fields */ + mailimf_fields_fields_init(&single_fields, fields); + /* do the things */ + mailimf_fields_free(fields); + + return 0; +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="c385.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x1094.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Internet Message Format</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c385.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Parser functions</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/API/x88.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/API/x88.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,600 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>List</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan! API" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Tools and datatypes" +HREF="c16.htm"><LINK +REL="PREVIOUS" +TITLE="Tools and datatypes" +HREF="c16.htm"><LINK +REL="NEXT" +TITLE="Hash table" +HREF="x161.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan! API</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="c16.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 2. Tools and datatypes</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x161.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="CLIST" +>List</A +></H1 +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +typedef struct clist_s clist; + +typedef clistcell clistiter; + </PRE +><P +> <B +CLASS="COMMAND" +>clist()</B +> is a list of cells. + Each cell of the list contains one element. This element is a + pointer. An iterator (<B +CLASS="COMMAND" +>clistiter</B +>) is a + pointer to an element of the list. With an iterator, we can + get the previous element of the list, the next element of the + list and the content of the element. + </P +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CLIST-NEW" +>clist_new and clist_free</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>clist * clist_new(void); + +void clist_free(clist *); + </PRE +><P +> <B +CLASS="COMMAND" +>clist_new()</B +> allocates a new empty list and + returns it. + </P +><P +> <B +CLASS="COMMAND" +>clist_free()</B +> frees the entire list with + its cells. + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN101" +></A +><P +><B +>Example 2-5. clist creation</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + goto err; + + r = clist_append(list, "foo-bar"); + if (r < 0) + + clist_free(list); + + exit(EXIT_SUCCESS); + + free: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CLIST-COUNT" +>clist_isempty and clist_count</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int clist_isempty(clist *); + +int clist_count(clist *); + </PRE +><P +> <B +CLASS="COMMAND" +>clist_isempty()</B +> returns 1 if the list is + empty, else it is 0. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_count()</B +> returns the number of + elements in the list. + Complexity is O(1). + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CLIST-BEGIN" +>running through clist</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>clistiter * clist_begin(clist *); + +clistiter * clist_end(clist *); + +clistiter * clist_next(clistiter *); + +clistiter * clist_previous(clistiter *); + +void * clist_content(clistiter *); + +void * clist_nth_data(clist * lst, int index); + +clistiter * clist_nth(clist * lst, int index); + </PRE +><P +> <B +CLASS="COMMAND" +>clist_begin()</B +> returns an iterator to the + first element of the list. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_end()</B +> returns an iterator to the last + element of the list. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_next()</B +> returns an iterator to the + next element of the list. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_previous()</B +> returns an iterator to the + previous element of the list. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_content()</B +> returns the element + contained in the cell pointed by the iterator in the list. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_nth()</B +> returns an iterator on the + <B +CLASS="COMMAND" +>index</B +>-th element of the list. + Complexity is O(n). + </P +><P +> <B +CLASS="COMMAND" +>clist_nth_data()</B +> returns the index-th + element of the list. + Complexity is O(n). + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN129" +></A +><P +><B +>Example 2-6. displaying content of clist</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(void) +{ + clist * list; + clistiter * iter; + + list = build_string_list(); + if (list == NULL) + goto err; + + for(iter = clist_begin(list) ; iter != NULL ; iter = + clist_next(iter)) { + char * str; + + str = clist_content(iter); + printf("%s\n", str); + } + + clist_free(list); + + exit(EXIT_SUCCESS); + + free: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CLIST-APPEND" +>clist modification</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>int clist_prepend(clist *, void *); + +int clist_append(clist *, void *); + +int clist_insert_before(clist *, clistiter *, void *); + +int clist_insert_after(clist *, clistiter *, void *); + +clistiter * clist_delete(clist *, clistiter *); + </PRE +><P +> <B +CLASS="COMMAND" +>clist_prepend()</B +> adds an element at the + beginning of the list. Returns 0 on sucess, -1 on error. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_append()</B +> adds an element at the end + of the list. Returns 0 on sucess, -1 on error. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_insert_before()</B +> adds an element + before the element pointed by the given iterator in the + list. Returns 0 on sucess, -1 on error. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_insert_after()</B +> adds an element after + the element pointed by the given iterator in the list. + Returns 0 on sucess, -1 on error. + Complexity is O(1). + </P +><P +> <B +CLASS="COMMAND" +>clist_delete()</B +> the elements pointed by + the given iterator in the list and returns an iterator to + the next element of the list. + Complexity is O(1). + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN145" +></A +><P +><B +>Example 2-7. deleting elements in a clist</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +voir print_content(void * content, void * user_data) +{ + char * str; + + str = content; + + printf("%s\n", str); +} + +int main(void) +{ + clist * list; + clistiter * iter; + + list = build_string_list(); + if (list == NULL) + goto err; + + iter = = clist_begin(list); + while (iter != NULL) + char * str; + + str = clist_content(iter); + if (strcmp(str, "foo-bar") == 0) + iter = clist_delete(list, cur); + else + iter = clist_next(iter); + } + + clist_foreach(list, print_content, NULL); + printf("\n"); + + clist_free(list); + + exit(EXIT_SUCCESS); + + free: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CLIST-FOREACH" +>clist_foreach</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>typedef void (* clist_func)(void *, void *); + +void clist_foreach(clist * lst, clist_func func, void * data); + </PRE +><P +> <B +CLASS="COMMAND" +>clist_foreach()</B +> apply a fonction to each + element of the list. + Complexity is O(n). + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CLIST-CONCAT" +>clist_concat</A +></H2 +><PRE +CLASS="PROGRAMLISTING" +>void clist_concat(clist * dest, clist * src); + </PRE +><P +> <B +CLASS="COMMAND" +>clist_concat()</B +> adds all the elements of src + at the end of dest. Elements are added in the same + order. src is an empty list when the operation is finished. + Complexity is O(1). + </P +><DIV +CLASS="EXAMPLE" +><A +NAME="AEN158" +></A +><P +><B +>Example 2-8. merging two clists</B +></P +><PRE +CLASS="PROGRAMLISTING" +>#include <libetpan/libetpan.h> + +int main(void) +{ + clist * list; + clist * list_2; + clistiter * iter; + + list = build_string_list(); + if (list == NULL) + goto err; + + list_2 = build_string_list_2(); + if (list == NULL) + goto free_list; + + clist_concat(list, list_2); + clist_free(list_2); + + for(iter = clist_begin(list) ; iter != NULL ; iter = + clist_next(iter)) { + char * str; + + str = clist_content(iter); + printf("%s\n", str); + } + + clist_free(list); + + exit(EXIT_SUCCESS); + + free_list: + clist_free(list); + err: + exit(EXIT_FAILURE); +} + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="c16.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x161.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Tools and datatypes</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c16.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Hash table</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/DOCUMENTATION ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/DOCUMENTATION Wed Dec 20 15:28:56 2006 @@ -0,0 +1,654 @@ +1/ Introduction +--------------- + +libEtPan! is mainly a library that will handle all kind of mailbox access. +For example: IMAPrev4, POP3, NNTP, mbox, MH. + +You have two kinds of mailbox access, either using low-level functions +with a different interface for each kind of access or using higher-level +functions, using a driver to wrap the higher-level API. + + +2/ Low-level +------------ + +2.1/ IMAP4rev1 - Internet Message Access Protocol - Version 4rev1 +----------------------------------------------------------------- + +Each command of the IMAP4rev1 Standard (RFC 2060) is implemented in +the IMAP4rev1 module. Directory imap/. + +2.1.1/ References + +- RFC 2060 - INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1 +- draft-crispin-imapv-15.txt + +Not yet implemented : + +- draft-crispin-imapv-20.txt + +2.1.2/ Dependencies + +- tools/ + +2.1.3/ Files descriptions + +description of header files : +mailimap.[ch] -- functions that implements each IMAP4rev1 command +mailimap_helper.[ch] -- helper interface for the previous functions +mailimap_types.[ch] -- definition of types and constructors for these + types +mailimap_types_helper.[ch] -- contains function definitions that will help + to create data necessary to use IMAP4rev1 module +mailimap_socket.[ch] -- provides a function to connect to an + IMAP4rev1 server over TCP +mailimap_ssl.[ch] -- provides a function to connect to an + IMAP4rev1 server over TLS layer + +2.1.4/ Interface + +Include for this module is mailimap.h and includes all other headers. + + +The interface of IMAP4rev1 is documented in the following files : + +mailimap.h +mailimap_types.h +mailimap_types_helper.h + + +2.2/ POP3 - Post Office Protocol - Version 3 +-------------------------------------------- + +Each command of the POP3 Standard (RFC 1939 and RFC 2449) is implemented +in the POP3 module. Directory pop3/. + +2.1.1/ References + +- RFC 1939 - Post Office Protocol - Version 3 +- RFC 2449 - POP3 Extension Mechanism (CAPA) + +Not yet implemented : + +- RFC 1734 - POP3 AUTHentication command + +2.1.2/ Dependencies + +- tools/ + +2.2.3/ Files descriptions + +mailpop3.[ch] -- functions that implements each POP3 command +mailpop3_helper.[ch] -- helper interface for the previous functions +mailpop3_socket.[ch] -- provides a function to connect to a + POP3 server over TCP +mailpop3_ssl.[ch] -- provides a function to connect to a + POP3 server over TLS layer + +2.2.4/ Interface + +Include for this module is mailpop3.h and includes all other headers. + +There is not yet documentation for POP3 module. + + +2.3/ NNTP - Network News Transfer Protocol +------------------------------------------ + +Each command of the NNTP Standard (RFC 977 and RFC 2980) is implemented +in the NNTP module. Directory nntp/. + +2.3.1/ References + +- RFC 977 - Network News Transfer Protocol +- RFC 2980 - Common NNTP Extensions + +Not yet implemented : + +- RFC 1036 - Standard for Interchange of USENET Messages +- son of RFC 1036 : FTP://zoo.toronto.edu/pub/news.txt.Z + +2.3.2/ Dependencies + +- tools/ + +2.3.3/ Files descriptions + +newsnntp.[ch] -- functions that implements each NNTP command +newsnntp_socket.[ch] -- provides a function to connect to a + NNTP server over TCP +newsnntp_ssl.[ch] -- provides a function to connect to a + POP3 server over TLS layer + +2.3.4/ Interface + +Include for this module is newsnntp.h and includes all other headers. + +There is not yet documentation for NNTP module. + + +2.4/ mbox +--------- + +The mbox module provides a set of functions to manipulate mbox mailboxes. +These functions make a safe lock on the mailbox they work with. +This module will assign to each message a unique message identifier +so that we can work with message numbers in mbox files without other +programs interfer. +Directory mbox/. + +2.4.1/ References + +- http://wp.netscape.com/eng/mozilla/2.0/relnotes/demo/content-length.html +- http://www.qmail.org/qmail-manual-html/man5/mbox.html + +2.4.2/ Dependencies + +- tools/ +- imf/ + +2.5.3/ Specific to libEtPan! + +- "X-LibEtPan-UID" header + +2.5.4/ Files descriptions + +mailmbox.[ch] -- functions to manipulate mbox mailboxes. +mailmbox_parse.[ch] -- this module is in charge of parsing the + mbox file content +mailmbox_types.[ch] -- definition of types and constructors for these + types + +2.4.5/ Interface + +Include for this module is mailmbox.h and includes all other headers. + +There is not yet documentation for mbox module. + + +2.5/ MH +------- + +The MH module provides a set of functions to manipulate MH mailboxes. +Directory mh/. + +2.5.1/ References + +- almost none + +2.5.2/ Dependencies + +- tools/ + +2.5.3/ Files descriptions + +mailmh.[ch] -- functions to manipulate MH mailboxes. + + +2.5.4/ Interface + +Include for this module is mailmh.h. + +There is not yet documentation for MH module. + + +2.6/ IMF - Internet Message Format +---------------------------------- + +The IMF module provides functions to parse data given in RFC 2822 +format (Internet Message Format). +Directory imf/. + +2.6.1/ References + +- RFC 2822 - Internet Message Format (Not entirely implemented) +- RFC 2076 - Common Internet Message Headers + +Not yet implemented : + +- RFC 2298 - An Extensible Message Format + for Message Disposition Notifications + +2.6.2/ Dependencies + +- tools/ + +2.6.3/ Files descriptions + +mailimf.[ch] -- functions to parse RFC 2822 messages. +mailimf_types.[ch] -- definition of types and constructors for these + types +mailimf_types_helper.[ch] -- contains function definitions that will help + to create data necessary to use IMF module. +mailimf_write.[ch] -- functions that output RFC 2822 messages or + sub-part of the messages in a (FILE *). + +2.6.4/ Interface + +Include for this module is mailimf.h and includes all other headers. + +The interface of IMAP4rev1 is documented in the following files : + +mailimf.h +mailimf_types.h +mailimf_types_helper.h +mailimf_write.h + + +2.7/ MIME - Multipurpose Internet Mail Extensions +------------------------------------------------- + +The MIME module provides functions to parse structure of MIME messages. +Directory mime/. + +2.7.1/ References + +- RFC 2045 - Multipurpose Internet Mail Extensions (MIME) Part One: Format of + Internet Message Bodies. +- RFC 2047 - MIME (Multipurpose Internet Mail Extensions) Part Three: Message + Header Extensions for Non-ASCII Text. +- RFC 2183 - Communicating Presentation Information in Internet Messages: + The Content-Disposition Header Field + +Not implemented : + +- RFC 2046 - Multipurpose Internet Mail Extensions (MIME) Part Two: Media + Types. + +2.7.2/ Dependencies + +- tools/ +- imf/ + +2.7.3/ Files descriptions + +mailmime.[ch] -- functions to parse the MIME fields (RFC 2045). +mailmime_content.[ch] -- functions to parse the MIME message. You get + the different parts and you can decode them. +mailmime_decode.[ch] -- functions to parse the MIME-encoded fields. +mailmime_disposition.[ch] -- functions to parse the Content-Disposition field + (RFC 2183) +mailmime_types.[ch] -- definition of types and constructors for these + types +mailmime_types_helper.[ch] -- contains function definitions that will help + to create data necessary to use MIME module. +mailmime_write.[ch] -- functions that output MIME messages or + sub-part of the messages in a (FILE *). + +2.7.4/ Interface + +Include for this module is mailmime.h and includes all other headers. + +There is not yet documentation for MIME module. + + +2.8/ SMTP - Simple Mail Transfer Protocol +----------------------------------------- + +Each command of the SMTP Standard (RFC 2821 and RFC 1891) is implemented +in the SMTP module. Directory smtp/. + +2.8.1/ References + +- RFC 2821 - Simple Mail Transfer Protocol (Not entirely implemented) +- RFC 1891 - SMTP Service Extension for Delivery Status Notifications + +2.8.2/ Depencencies + +- tools/ + +2.8.3/ Files descriptions + +mailsmtp.[ch] -- functions that implements each SMTP command +mailsmtp_helper.[ch] -- functions to get an easier use of SMTP module +mailsmtp_socket.[ch] -- provides a function to connect to a + SMTP server over TCP +mailsmtp_ssl.[ch] -- provides a function to connect to a + SMTP server over TLS layer +mailsmtp_types.h -- definition of types + +2.8.4/ Interface + +Include for this module is mailsmtp.h and includes all other headers. + +There is not yet documentation for MIME module. + + +2.9/ Miscellaneous + +2.9.1/ References + +- RFC 2234 - Augmented BNF for Syntax Specifications: ABNF +- RFC 2595 - Using TLS with IMAP, POP3 and ACAP + +2.9.2/ Tools + +tools/ directory contains some tools functions and useful data structures. + +alloc.h -- a wrapper on malloc() +carray.[ch] -- an array, that grows automatically when elements + are added. +charconv.[ch] -- character set converter. For example, it will + translate an iso-8859-1 string to an utf-8 string. +chash.[ch] -- a hash table which keys can be anything +cinthash.[ch] -- a hash table which keys are integers + (should be removed and replaced with chash) +clist.[ch] -- a double-linked list +connect.[ch] -- easy interface to connect a TCP server +hmac_md5.h +md5.[ch] +md5global.h -- MD5 calculation +mail.h -- some constants +maildb_helper.[ch] -- wrappers to DB 2.x 3.x or 4.x +maillock.[ch] -- safely lock a given file +mailstream.[ch] -- stream interface - buffered reading and writing + on files/socket/SSL connection +mailstream_helper.[ch] -- useful functions for stream + (for example: read a line) +mailstream_low.[ch] -- driver interface for a stream +mailstream_socket.[ch] -- stream driver for file descriptors (includes socket) +mailstream_ssl.[ch] -- stream driver for SSL connection +mailstream_types.h -- data structure definition +mapping.[ch] -- map parts of files in memory (no more used) +mmapstring.[ch] -- a string, that grows automatically when data + are added. + + +3/ Higher-level +--------------- + +The higher level will allow us to query folder informations or to get +messages information or content. + +There is four kinds of identities : +- storage +- folders +- session +- messages + +In the higher-level interface, you manipulate data types from IMF and +MIME module, plus additionnal data types of higher-level. + + +3.1/ Objects +------------ + +3.1.1/ Storage + +A storage (struct mail_storage) represents whether a server or +a main path, It can be an IMAP server, the root path of a MH or a mbox file. + + +3.1.2/ Folders + +A folder can be created from a storage. +Folders (struct mail_folder) are the mailboxes we can choose in the +server or as sub-folder of the main path. + +Folders for IMAP are the IMAP mailboxes, for MH this is one of the +folder of the MH storage, for mbox, there is only one folder, the +mbox file content; + + +3.1.3/ Session + +Storage and folders communicate with the lower-layer through the +mail session data structure. + +A mail session (struct mailsession) is a mail access to a server +or a mail access in the local file system. It allow us to send commands +to the mail access. + +A mail storage is using a mail session to communicate. +A folder folder also uses a mail session to get information or to send +information. It can be the same session or not, depdending of the +implementation. + + +3.1.4/ Messages + +From a session, we can get a message (struct mailmessage) to read. + + +3.2/ Drivers +------------ + +For a mail access, three drivers exist. +One for storage, one for session, one for message. +Note that the folder access rely only on session driver. + + +3.2.1/ storage driver interface + + mail_storage_driver is the driver structure for mail storage + + - name is the name of the driver + + - connect() connects the storage to the remote access or to + the path in the local filesystem. + + - get_folder() can have two kinds of behaviour. + Either it creates a new session and independant from the session + used by the storage and select the given mailbox or + it selects the given mailbox in the current session. + It depends on the efficiency of the mail driver. + + - free_data() frees the data created with mail_storage constructor. + + a constructor for each kind of access has to be implemented. + + +3.2.2/ session driver interface + + maildriver is the driver structure for mail sessions + + - name is the name of the driver + + - initialize() is the function that will initializes a data structure + specific to the driver, it returns a value that will be stored + in the field data of the session. + The field data of the session is the state of the session, + the internal data structure used by the driver. + It is called when creating the mailsession structure with + mailsession_new(). + + - uninitialize() frees the structure created with initialize() + + - parameters() implements functions specific to the given mail access + + - connect_stream() connects a stream to the session + + - connect_path() notify a main path to the session + + - starttls() changes the current stream to a TLS stream + + - login() notifies the user and the password to authenticate to the + session + + - logout() exits the session and closes the stream + + - noop() does no operation on the session, but it can be + used to poll for the status of the connection. + + - check_folder() makes a checkpoint of the session + + - select_folder() selects a mailbox + + - expunge_folder() deletes all messages marked \Deleted + + - status_folder() queries the status of the folder + (number of messages, number of recent messages, number of + unseen messages) + + - append_message() adds a RFC 2822 message to the current + given mailbox + + - get_messages_list() returns the list of message numbers + of the current mailbox. + + - get_envelopes_list() fills the parsed fields in the + mailmessage structures of the mail_envelopes_list. + + - remove_message() removes the given message from the mailbox. + The message is permanently deleted. + + - get_message returns a mailmessage structure that corresponds + to the given message number. + + +3.2.3/ message driver interface + + mailmessage_driver is the driver structure to get information from messages. + + - name is the name of the driver + + - initialize() is the function that will initializes a data structure + specific to the driver, it returns a value that will be stored + in the field data of the mailsession. + The field data of the session is the state of the session, + the internal data structure used by the driver. + It is called when initializing the mailmessage structure with + mailmessage_init(). + + - uninitialize() frees the structure created with initialize(). + It will be called by mailmessage_free(). + + - flush() will free from memory all temporary structures of the message + (for example, the MIME structure of the message). + + - fetch_result_free() will free all strings resulted by fetch() or + any fetch_xxx() functions that returns a string. + + - fetch() returns the content of the message (headers and text). + + - fetch_header() returns the content of the headers. + + - fetch_body() returns the message text (message content without headers) + + - fetch_size() returns the size of the message content. + + - get_bodystructure() returns the MIME structure of the message. + + - fetch_section() returns the content of a given MIME part + + - fetch_section_header() returns the header of the message + contained by the given MIME part. + + - fetch_section_mime() returns the MIME headers of the + given MIME part. + + - fetch_section_body() returns the text (if this is a message, this is the + message content without headers) of the given MIME part. + + - fetch_envelope() returns a mailimf_fields structure, with a list of + fields chosen by the driver. + + - get_flags() returns a the flags related to the message. + When you want to get flags of a message, you have to make sure to + call get_flags() at least once before using directly message->flags. + + +3.3/ Higher level interface +--------------------------- + +3.3.1/ Files descriptions + +generic_cache.[ch] -- functions that implements cache and + flags storing mechanism +imapdriver.[ch] -- IMAP driver for session +imapdriver_cached.[ch] -- IMAP driver for session, using cache, + IMAP already has flags. +imapdriver_cached_message.[ch] -- IMAP driver for message, using cache + IMAP already has flags. +imapdriver_message.[ch] -- IMAP driver for message +imapdriver_types.[ch] -- tools function for IMAP driver (types + conversion from IMAP module). +imapstorage.[ch] -- IMAP driver for storage +imfcache.[ch] -- implements cache for parsed fields +libetpan.h -- includes all necessary header files to + use libEtPan! +maildriver.[ch] -- wrappers to calls to the session driver +maildriver_tools.[ch] -- default implementation for drivers, + when the driver does not parse the + messages. +maildriver_types.[ch] -- data types declaration and constructors +maildriver_types_helper.[ch] -- easy data creation +mailmessage.[ch] -- wrappers to calls to the message driver +mailstorage.[ch] -- storage creation, calls to the storage + driver and implementation of folders. +mailstorage_tools.[ch] -- tools for storage (connection) +mailthread.[ch] -- threading: collection of the mails + into a treee +mboxdriver.[ch] -- mbox driver for session +mboxdriver_cached.[ch] -- mbox driver for session, using flags + and cache +mboxdriver_cached_message.[ch] -- mbox driver for message, using flags + and cache +mboxdriver_message.[ch] -- mbox driver for message +mboxdriver_tools.[ch] -- mbox driver common functions +mboxstorage.[ch] -- mbox driver for storage +mhdriver.[ch] -- MH driver for session +mhdriver_cached.[ch] -- MH driver for session, using flags + and cache +mhdriver_cached_message.[ch] -- MH driver for message, using flags + and cache. +mhdriver_message.[ch] -- MH driver for message +mhdriver_tools.[ch] -- MH driver common functions +mhstorage.[ch] -- MH driver for storage +nntpdriver.[ch] -- NNTP driver for session +nntpdriver_cached.[ch] -- NNTP driver for session, using flags + and cache +nntpdriver_cached_message.[ch] -- NNTP driver for message, using flags + and cache +nntpdriver_message.[ch] -- NNTP driver for message +nntpdriver_tools.[ch] -- NNTP driver common functions +nntpstorage.[ch] -- NNTP driver for storage +pop3driver.[ch] -- POP3 driver for session +pop3driver_cached.[ch] -- POP3 driver for session, using flags + and cache +pop3driver_cached_message.[ch] -- POP3 driver for message, using flags + and cache +pop3driver_message.[ch] -- POP3 driver for message +pop3driver_tools.[ch] -- POP3 driver common functions +pop3storage.[ch] -- POP3 driver for storage + + +3.3.2/ Interfaces + +Include for this module is libetpan.h and includes all other headers. + + +The interface of higher layer is documented in the following files : + +maildriver.h +maildriver_types.h +maildriver_types_helper.h +mailmessage.h +mailstorage.h +mailstorage_types.[h] +mailthread.h + + +4/ Architecture +--------------- + +(see layer.fig) + + +5/ Example of use +----------------- + +You can find some example in tests/ + + +6/ Constraints +-------------- + +- libEtPan! must run on a system where mmap() is available. + +- for mbox particularly, libEtPan! make assumption on the fact that a + file can be entirely mapped into memory. But if you don't read + mailboxes of 1 Go, it should be fine. + + + Added: freeswitch/trunk/libs/libetpan/doc/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,21 @@ +# DSL = /usr/lib/sgml/stylesheet/dsssl/docbook/nwalsh/html/docbook.dsl +DSL = /usr/share/sgml/docbook/stylesheet/dsssl/modular/html/docbook.dsl +JADE = jade +HTML_RENDER = lynx -force_html -nolist -dump + +SOURCES = API README + +all: + @for i in $(SOURCES); do \ + echo $$i - building html; \ + $(JADE) -t sgml -V nochunks -d $(DSL) $$i.sgml > $$i.html; \ + \ + echo $$i - building txt; \ + $(HTML_RENDER) $$i.html > $$i.txt; \ + \ + echo $$i - building multipage HTML; \ + mkdir -p $$i; \ + cd $$i; \ + $(JADE) -t sgml -d $(DSL) ../$$i.sgml; \ + cd ..; \ + done Added: freeswitch/trunk/libs/libetpan/doc/README.html ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/README.html Wed Dec 20 15:28:56 2006 @@ -0,0 +1,780 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>libEtPan!</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"></HEAD +><BODY +CLASS="BOOK" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="BOOK" +><A +NAME="LIBETPAN-README" +></A +><DIV +CLASS="TITLEPAGE" +><H1 +CLASS="TITLE" +><A +NAME="AEN2" +>libEtPan!</A +></H1 +><H3 +CLASS="AUTHOR" +><A +NAME="AEN6" +></A +>Viet Hoa DINH</H3 +><P +CLASS="COPYRIGHT" +>Copyright © 2003 DINH Viet Hoa</P +><HR></DIV +><DIV +CLASS="TOC" +><DL +><DT +><B +>Table of Contents</B +></DT +><DT +>1. <A +HREF="#INTRODUCTION" +>Introduction</A +></DT +><DD +><DL +><DT +><A +HREF="#DESCRIPTION" +>Description</A +></DT +><DT +><A +HREF="#AUTHOR" +>Author</A +></DT +><DD +><DL +><DT +><A +HREF="#MAIN-AUTH" +>Main author</A +></DT +><DT +><A +HREF="#CONTRIB" +>Contributors</A +></DT +></DL +></DD +></DL +></DD +><DT +>2. <A +HREF="#INSTALLATION" +>Installation</A +></DT +><DD +><DL +><DT +><A +HREF="#DEPENDENCIES" +>Dependencies</A +></DT +><DD +><DL +><DT +><A +HREF="#DEPEND-USERS" +>Dependencies for users</A +></DT +><DT +><A +HREF="#DEPEND-DEVELOPERS" +>Dependencies for developers</A +></DT +></DL +></DD +><DT +><A +HREF="#PACKAGES" +>Existing packages</A +></DT +><DD +><DL +><DT +><A +HREF="#PACKAGE-FREEBSD" +>FreeBSD</A +></DT +><DT +><A +HREF="#PACKAGE-DEBIAN" +>Debian</A +></DT +><DT +><A +HREF="#PACKAGE-MANDRAKE" +>Mandrake Linux</A +></DT +></DL +></DD +><DT +><A +HREF="#COMPILATION" +>Compilation</A +></DT +><DD +><DL +><DT +><A +HREF="#COMPILE-FREEBSD" +>FreeBSD</A +></DT +><DT +><A +HREF="#COMPILE-MACOSX" +>Mac OS X</A +></DT +><DT +><A +HREF="#LINUX" +>Linux</A +></DT +><DT +><A +HREF="#CONFIGURE" +>configure</A +></DT +><DT +><A +HREF="#INSTALL" +>Compile and install</A +></DT +></DL +></DD +></DL +></DD +><DT +>3. <A +HREF="#USE" +>Use of libEtPan!</A +></DT +><DD +><DL +><DT +><A +HREF="#HOTMAIL" +>How to open an Hotmail mailbox</A +></DT +></DL +></DD +></DL +></DIV +><DIV +CLASS="CHAPTER" +><HR><H1 +><A +NAME="INTRODUCTION" +></A +>Chapter 1. Introduction</H1 +><DIV +CLASS="SECT1" +><H2 +CLASS="SECT1" +><A +NAME="DESCRIPTION" +>Description</A +></H2 +><P +> The purpose of this mail library is to provide a portable, + efficient middleware for different kinds of mail access + (IMAPrev4, POP3, NNTP, mbox, MH, Maildir). + </P +><P +> You have two kinds of mailbox access, either using low-level + functions with a different interface for each kind of access + or using higher-level functions, using a driver to wrap the + higher-level API. The API will be the same for each kind of + mail access using the higher-level API. + </P +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="AUTHOR" +>Author</A +></H2 +><DIV +CLASS="SECT2" +><H3 +CLASS="SECT2" +><A +NAME="MAIN-AUTH" +>Main author</A +></H3 +><P +> DINH Viet Hoa <CODE +CLASS="EMAIL" +><<A +HREF="mailto:hoa@users.sourceforge.net" +>hoa@users.sourceforge.net</A +>></CODE +> + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CONTRIB" +>Contributors</A +></H3 +><P +> <P +></P +><UL +><LI +><P +> Wim Delvaux + </P +></LI +><LI +><P +> Melvin Hadasht + </P +></LI +><LI +><P +> David Woodhouse + </P +></LI +><LI +><P +> Juergen Graf + </P +></LI +><LI +><P +> Zsolt VARGA + </P +></LI +><LI +><P +> Gael Roualland + </P +></LI +><LI +><P +> Toni Willberg + </P +></LI +><LI +><P +> Rajko Albrecht + </P +></LI +><LI +><P +> Nikita V. Youshchenko + </P +></LI +><LI +><P +> Frederic Devernay + </P +></LI +><LI +><P +> Michael Leupold + </P +></LI +><LI +><P +> Colin Leroy + </P +></LI +></UL +> + </P +></DIV +></DIV +></DIV +><DIV +CLASS="CHAPTER" +><HR><H1 +><A +NAME="INSTALLATION" +></A +>Chapter 2. Installation</H1 +><DIV +CLASS="SECT1" +><H2 +CLASS="SECT1" +><A +NAME="DEPENDENCIES" +>Dependencies</A +></H2 +><DIV +CLASS="SECT2" +><H3 +CLASS="SECT2" +><A +NAME="DEPEND-USERS" +>Dependencies for users</A +></H3 +><P +></P +><UL +><LI +><P +> <A +HREF="http://www.openssl.org" +TARGET="_top" +>OpenSSL</A +> + (optional but recommended) + </P +></LI +><LI +><P +> <A +HREF="http://www.sleepycat.com" +TARGET="_top" +>Berkeley + DB</A +> (optional but recommended) + </P +></LI +><LI +><P +> POSIX Thread (required) + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="DEPEND-DEVELOPERS" +>Dependencies for developers</A +></H3 +><P +></P +><UL +><LI +><P +> <A +HREF="http://www.gnu.org/software/autoconf" +TARGET="_top" +> autoconf + </A +> + 2.13 + </P +></LI +><LI +><P +> <A +HREF="http://www.gnu.org/software/automake" +TARGET="_top" +> automake + </A +> + 1.4 + </P +></LI +><LI +><P +> <A +HREF="http://www.gnu.org/software/libtool/libtool.html" +TARGET="_top" +> libtool + </A +> + 1.4.3 + </P +></LI +><LI +><P +> jade and some SGML tools will be required + </P +></LI +></UL +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="PACKAGES" +>Existing packages</A +></H2 +><P +> Before you try to compile it, you have to know that packages + exist for some systems. + </P +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="PACKAGE-FREEBSD" +>FreeBSD</A +></H3 +><P +> you can find it in ports/mail/libetpan. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="PACKAGE-DEBIAN" +>Debian</A +></H3 +><P +> This is in the package collection. + </P +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="PACKAGE-MANDRAKE" +>Mandrake Linux</A +></H3 +><P +> This is in the package collection. + </P +></DIV +></DIV +><DIV +CLASS="SECT1" +><HR><H2 +CLASS="SECT1" +><A +NAME="COMPILATION" +>Compilation</A +></H2 +><P +> Generic installation instructions are in the + <TT +CLASS="FILENAME" +>INSTALL</TT +> file + You can pass the following extra options to configure : + </P +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="COMPILE-FREEBSD" +>FreeBSD</A +></H3 +><P +></P +><UL +><LI +><P +> make sure libiconv is installed from the ports collection (see + <B +CLASS="COMMAND" +>pkg_info</B +>). + </P +></LI +><LI +><P +> issue configure with the following parameter: + <PRE +CLASS="SCREEN" +><SAMP +CLASS="PROMPT" +>$</SAMP +> <KBD +CLASS="USERINPUT" +>./configure --with-libiconv-prefix=/usr/local</KBD +> + </PRE +> + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="COMPILE-MACOSX" +>Mac OS X</A +></H3 +><P +></P +><UL +><LI +><P +> in tests/option-parser.c, change the inclusion + of <TT +CLASS="FILENAME" +>getopt.h</TT +> to + <TT +CLASS="FILENAME" +>gnugetopt/getopt.h</TT +> + </P +></LI +><LI +><P +> in <TT +CLASS="FILENAME" +>tests/Makefile</TT +>, add + <B +CLASS="COMMAND" +>-I/sw/include</B +> for the + <B +CLASS="COMMAND" +>CFLAGS</B +> and + -L/sw/lib -lgnugetopt for the LDFLAGS. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="LINUX" +>Linux</A +></H3 +><P +></P +><UL +><LI +><DIV +CLASS="WARNING" +><P +></P +><TABLE +CLASS="WARNING" +BORDER="1" +WIDTH="90%" +><TR +><TD +ALIGN="CENTER" +><B +>Warning</B +></TD +></TR +><TR +><TD +ALIGN="LEFT" +><P +> Since libEtPan! is making high usage of + <B +CLASS="COMMAND" +>mmap()</B +> even for + writing, when your mailboxes are on + <B +CLASS="COMMAND" +>NFS</B +> filesystem with + a Linux server, it is advised to use option + <B +CLASS="COMMAND" +>no_subtree_check</B +> in + <TT +CLASS="FILENAME" +>/etc/exports</TT +>. + This should avoid corruption of data. + </P +><P +> The problem exist in Linux 2.4.22 and earlier versions. + </P +></TD +></TR +></TABLE +></DIV +></LI +><LI +><P +> On RedHat systems, you have to configure using the + following command line : + <B +CLASS="COMMAND" +>./configure --with-openssl=/usr/kerberos</B +> + </P +></LI +><LI +><P +> On Debian systems, if the <B +CLASS="COMMAND" +>./autogen</B +> + script fails on missing <B +CLASS="COMMAND" +>AM_ICONV</B +>, you + have to install <B +CLASS="COMMAND" +>gettext</B +> package. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="CONFIGURE" +>configure</A +></H3 +><P +> You can use the following options : + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>--enable-debug</B +> Compiles with + debugging turned on + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>--enable-optim</B +> Turns on some + optimizations flags for gcc + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>--without-openssl</B +> Disables OpenSSL (do + not look for it) + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><HR><H3 +CLASS="SECT2" +><A +NAME="INSTALL" +>Compile and install</A +></H3 +><P +> Download the package and do the following : + </P +><PRE +CLASS="PROGRAMLISTING" +>$ tar xzvf libetpan-XX.XX.tar.gz # to decompress the package + +$ cd libetpan-XX.XX + +$ ./configure --help # to get options of configure + +$ ./configure # you can specify your own options + +$ make # to compile the package + +$ su + +# make install + +# logout + </PRE +></DIV +></DIV +></DIV +><DIV +CLASS="CHAPTER" +><HR><H1 +><A +NAME="USE" +></A +>Chapter 3. Use of libEtPan!</H1 +><DIV +CLASS="SECT1" +><H2 +CLASS="SECT1" +><A +NAME="HOTMAIL" +>How to open an Hotmail mailbox</A +></H2 +><P +> If you wish to access hotmail using libEtPan!, you can, by + using <A +HREF="http://hotwayd.sf.net" +TARGET="_top" +>hotwayd</A +>. + Then, create a POP3 storage with the given parameters : + command as clear text for connection type + (<B +CLASS="COMMAND" +>CONNECTION_TYPE_COMMAND</B +>), + <B +CLASS="COMMAND" +>"/usr/bin/hotwayd"</B +> + as command, plain text authentication + (<B +CLASS="COMMAND" +>ePOP3_AUTH_TYPE_PLAIN</B +>), + full hotmail address as login + (<B +CLASS="COMMAND" +>foobar@hotmail.com</B +> or + <B +CLASS="COMMAND" +>foobar@hotmail.com/mailbox_name</B +> if you want + to access a specific mailbox) and give your password. + </P +></DIV +></DIV +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/README.sgml ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/README.sgml Wed Dec 20 15:28:56 2006 @@ -0,0 +1,388 @@ +<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN"> + +<book id="libetpan-readme"> + <bookinfo> + <date>2003-12-03</date> + <title>libEtPan!</title> + <authorgroup> + <author> + <firstname>Viet Hoa</firstname> + <surname>DINH</surname> + </author> + </authorgroup> + <copyright> + <year>2003</year> + <holder>DINH Viet Hoa</holder> + </copyright> + </bookinfo> + <toc></toc> + + <chapter id="introduction"> + <title>Introduction</title> + + <!-- description --> + <sect1 id="description"> + <title>Description</title> + <para> + The purpose of this mail library is to provide a portable, + efficient middleware for different kinds of mail access + (IMAPrev4, POP3, NNTP, mbox, MH, Maildir). + </para> + + <para> + You have two kinds of mailbox access, either using low-level + functions with a different interface for each kind of access + or using higher-level functions, using a driver to wrap the + higher-level API. The API will be the same for each kind of + mail access using the higher-level API. + </para> + </sect1> + + <!-- authors --> + <sect1 id="author"> + <title>Author</title> + <sect2 id="main-auth"> + <title>Main author</title> + <para> + DINH Viet Hoa <email>hoa@users.sourceforge.net</email> + </para> + </sect2> + <sect2 id="contrib"> + <title>Contributors</title> + <para> + <itemizedlist> + <listitem> + <para> + Wim Delvaux <!-- wim.delvaux.adaptiveplanet.com --> + </para> + </listitem> + <listitem> + <para> + Melvin Hadasht <!-- melvin.hadasht@free.fr --> + </para> + </listitem> + <listitem> + <para> + David Woodhouse <!-- dwmw2@infradead.org --> + </para> + </listitem> + <listitem> + <para> + Juergen Graf <!-- libetpan@codeguy.org --> + </para> + </listitem> + <listitem> + <para> + Zsolt VARGA <!-- redax@redax.hu --> + </para> + </listitem> + <listitem> + <para> + Gael Roualland <!-- gael.roualland@dial.oleane.com --> + </para> + </listitem> + <listitem> + <para> + Toni Willberg <!-- toniw@iki.fi --> + </para> + </listitem> + <listitem> + <para> + Rajko Albrecht <!-- ral@alwins-world.de --> + </para> + </listitem> + <listitem> + <para> + Nikita V. Youshchenko <!-- yoush@cs.msu.su --> + </para> + </listitem> + <listitem> + <para> + Frederic Devernay <!-- Frederic.Devernay@inrialpes.fr --> + </para> + </listitem> + <listitem> + <para> + Michael Leupold <!-- leupold@leunet.de --> + </para> + </listitem> + <listitem> + <para> + Colin Leroy <!-- colin@colino.net --> + </para> + </listitem> + </itemizedlist> + </para> + </sect2> + </sect1> + </chapter> + + <!-- installation --> + <chapter id="installation"> + <title>Installation</title> + + <sect1 id="dependencies"> + <title>Dependencies</title> + + <!-- dependencies for users --> + <sect2 id="depend-users"> + <title>Dependencies for users</title> + + <itemizedlist> + <listitem> + <para> + <ulink url="http://www.openssl.org">OpenSSL</ulink> + (optional but recommended) + </para> + </listitem> + <listitem> + <para> + <ulink url="http://www.sleepycat.com">Berkeley + DB</ulink> (optional but recommended) + </para> + </listitem> + <listitem> + <para> + POSIX Thread (required) + </para> + </listitem> + </itemizedlist> + </sect2> + <!-- dependencies for developers --> + <sect2 id="depend-developers"> + <title>Dependencies for developers</title> + + <itemizedlist> + <listitem> + <para> + <ulink url="http://www.gnu.org/software/autoconf"> + autoconf + </ulink> + 2.13 + </para> + </listitem> + <listitem> + <para> + <ulink url="http://www.gnu.org/software/automake"> + automake + </ulink> + 1.4 + </para> + </listitem> + <listitem> + <para> + <ulink + url="http://www.gnu.org/software/libtool/libtool.html"> + libtool + </ulink> + 1.4.3 + </para> + </listitem> + <listitem> + <para> + jade and some SGML tools will be required + </para> + </listitem> + </itemizedlist> + </sect2> + </sect1> + <!-- packages --> + <sect1 id="packages"> + <title>Existing packages</title> + + <para> + Before you try to compile it, you have to know that packages + exist for some systems. + </para> + + <!-- FreeBSD --> + <sect2 id="package-freebsd"> + <title>FreeBSD</title> + <para> + you can find it in ports/mail/libetpan. + </para> + </sect2> + + <!-- Debian --> + <sect2 id="package-debian"> + <title>Debian</title> + <para> + This is in the package collection. + </para> + </sect2> + + <!-- Mandrake --> + <sect2 id="package-mandrake"> + <title>Mandrake Linux</title> + <para> + This is in the package collection. + </para> + </sect2> + </sect1> + + <!-- compilation --> + <sect1 id="compilation"> + <title>Compilation</title> + + <para> + Generic installation instructions are in the + <filename>INSTALL</filename> file + You can pass the following extra options to configure : + </para> + + <!-- FreeBSD --> + <sect2 id="compile-freebsd"> + <title>FreeBSD</title> + <itemizedlist> + <listitem> + <para> + make sure libiconv is installed from the ports collection (see + <command>pkg_info</command>). + </para> + </listitem> + <listitem> + <para> + issue configure with the following parameter: + <screen> +<prompt>$</prompt> <userinput>./configure --with-libiconv-prefix=/usr/local</userinput> + </screen> + </para> + </listitem> + </itemizedlist> + </sect2> + + <!-- MacOS X --> + <sect2 id="compile-macosx"> + <title>Mac OS X</title> + <itemizedlist> + <listitem> + <para> + in tests/option-parser.c, change the inclusion + of <filename>getopt.h</filename> to + <filename>gnugetopt/getopt.h</filename> + </para> + </listitem> + <listitem> + <para> + in <filename>tests/Makefile</filename>, add + <command>-I/sw/include</command> for the + <command>CFLAGS</command> and + -L/sw/lib -lgnugetopt for the LDFLAGS. + </para> + </listitem> + </itemizedlist> + </sect2> + + <!-- Linux --> + <sect2 id="linux"> + <title>Linux</title> + <itemizedlist> + <listitem> + <warning> + <para> + Since libEtPan! is making high usage of + <command>mmap()</command> even for + writing, when your mailboxes are on + <command>NFS</command> filesystem with + a Linux server, it is advised to use option + <command>no_subtree_check</command> in + <filename>/etc/exports</filename>. + This should avoid corruption of data. + </para> + <para> + The problem exist in Linux 2.4.22 and earlier versions. + </para> + </warning> + </listitem> + <listitem> + <para> + On RedHat systems, you have to configure using the + following command line : + <command>./configure --with-openssl=/usr/kerberos</command> + </para> + </listitem> + <listitem> + <para> + On Debian systems, if the <command>./autogen</command> + script fails on missing <command>AM_ICONV</command>, you + have to install <command>gettext</command> package. + </para> + </listitem> + </itemizedlist> + </sect2> + + <!-- configure --> + <sect2 id="configure"> + <title>configure</title> + <para> + You can use the following options : + </para> + <itemizedlist> + <listitem> + <para> + <command>--enable-debug</command> Compiles with + debugging turned on + </para> + </listitem> + <listitem> + <para> + <command>--enable-optim</command> Turns on some + optimizations flags for gcc + </para> + </listitem> + <listitem> + <para> + <command>--without-openssl</command> Disables OpenSSL (do + not look for it) + </para> + </listitem> + </itemizedlist> + </sect2> + <sect2 id="install"> + <title>Compile and install</title> + <para> + Download the package and do the following : + </para> + <programlisting> +$ tar xzvf libetpan-XX.XX.tar.gz # to decompress the package + +$ cd libetpan-XX.XX + +$ ./configure --help # to get options of configure + +$ ./configure # you can specify your own options + +$ make # to compile the package + +$ su + +# make install + +# logout + </programlisting> + </sect2> + </sect1> + </chapter> + + <chapter id="use"> + <title>Use of libEtPan!</title> + + <sect1 id="hotmail"> + <title>How to open an Hotmail mailbox</title> + <para> + If you wish to access hotmail using libEtPan!, you can, by + using <ulink url="http://hotwayd.sf.net">hotwayd</ulink>. + Then, create a POP3 storage with the given parameters : + command as clear text for connection type + (<command>CONNECTION_TYPE_COMMAND</command>), + <command>"/usr/bin/hotwayd"</command> + as command, plain text authentication + (<command>ePOP3_AUTH_TYPE_PLAIN</command>), + full hotmail address as login + (<command>foobar@hotmail.com</command> or + <command>foobar@hotmail.com/mailbox_name</command> if you want + to access a specific mailbox) and give your password. + </para> + </sect1> + </chapter> +</book> Added: freeswitch/trunk/libs/libetpan/doc/README.txt ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/README.txt Wed Dec 20 15:28:56 2006 @@ -0,0 +1,200 @@ + +libEtPan! + +Viet Hoa DINH + + Copyright � 2003 DINH Viet Hoa + _________________________________________________________________ + + Table of Contents + 1. Introduction + + Description + Author + + Main author + Contributors + + 2. Installation + + Dependencies + + Dependencies for users + Dependencies for developers + + Existing packages + + FreeBSD + Debian + Mandrake Linux + + Compilation + + FreeBSD + Mac OS X + Linux + configure + Compile and install + + 3. Use of libEtPan! + + How to open an Hotmail mailbox + _________________________________________________________________ + +Chapter 1. Introduction + +Description + + The purpose of this mail library is to provide a portable, efficient + middleware for different kinds of mail access (IMAPrev4, POP3, NNTP, + mbox, MH, Maildir). + + You have two kinds of mailbox access, either using low-level functions + with a different interface for each kind of access or using + higher-level functions, using a driver to wrap the higher-level API. + The API will be the same for each kind of mail access using the + higher-level API. + _________________________________________________________________ + +Author + +Main author + + DINH Viet Hoa <hoa@users.sourceforge.net> + _________________________________________________________________ + +Contributors + + * Wim Delvaux + * Melvin Hadasht + * David Woodhouse + * Juergen Graf + * Zsolt VARGA + * Gael Roualland + * Toni Willberg + * Rajko Albrecht + * Nikita V. Youshchenko + * Frederic Devernay + * Michael Leupold + * Colin Leroy + _________________________________________________________________ + +Chapter 2. Installation + +Dependencies + +Dependencies for users + + * OpenSSL (optional but recommended) + * Berkeley DB (optional but recommended) + * POSIX Thread (required) + _________________________________________________________________ + +Dependencies for developers + + * autoconf 2.13 + * automake 1.4 + * libtool 1.4.3 + * jade and some SGML tools will be required + _________________________________________________________________ + +Existing packages + + Before you try to compile it, you have to know that packages exist for + some systems. + _________________________________________________________________ + +FreeBSD + + you can find it in ports/mail/libetpan. + _________________________________________________________________ + +Debian + + This is in the package collection. + _________________________________________________________________ + +Mandrake Linux + + This is in the package collection. + _________________________________________________________________ + +Compilation + + Generic installation instructions are in the INSTALL file You can pass + the following extra options to configure : + _________________________________________________________________ + +FreeBSD + + * make sure libiconv is installed from the ports collection (see + pkg_info). + * issue configure with the following parameter: +$ ./configure --with-libiconv-prefix=/usr/local + _________________________________________________________________ + +Mac OS X + + * in tests/option-parser.c, change the inclusion of getopt.h to + gnugetopt/getopt.h + * in tests/Makefile, add -I/sw/include for the CFLAGS and -L/sw/lib + -lgnugetopt for the LDFLAGS. + _________________________________________________________________ + +Linux + + * + + Warning + Since libEtPan! is making high usage of mmap() even for writing, when + your mailboxes are on NFS filesystem with a Linux server, it is + advised to use option no_subtree_check in /etc/exports. This should + avoid corruption of data. + The problem exist in Linux 2.4.22 and earlier versions. + * On RedHat systems, you have to configure using the following + command line : ./configure --with-openssl=/usr/kerberos + * On Debian systems, if the ./autogen script fails on missing + AM_ICONV, you have to install gettext package. + _________________________________________________________________ + +configure + + You can use the following options : + + * --enable-debug Compiles with debugging turned on + * --enable-optim Turns on some optimizations flags for gcc + * --without-openssl Disables OpenSSL (do not look for it) + _________________________________________________________________ + +Compile and install + + Download the package and do the following : +$ tar xzvf libetpan-XX.XX.tar.gz # to decompress the package + +$ cd libetpan-XX.XX + +$ ./configure --help # to get options of configure + +$ ./configure # you can specify your own options + +$ make # to compile the package + +$ su + +# make install + +# logout + + _________________________________________________________________ + +Chapter 3. Use of libEtPan! + +How to open an Hotmail mailbox + + If you wish to access hotmail using libEtPan!, you can, by using + hotwayd. Then, create a POP3 storage with the given parameters : + command as clear text for connection type (CONNECTION_TYPE_COMMAND), + "/usr/bin/hotwayd" as command, plain text authentication + (ePOP3_AUTH_TYPE_PLAIN), full hotmail address as login + (foobar@hotmail.com or foobar@hotmail.com/mailbox_name if you want to + access a specific mailbox) and give your password. Added: freeswitch/trunk/libs/libetpan/doc/README/book1.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/README/book1.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,237 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>libEtPan!</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="NEXT" +TITLE="Introduction" +HREF="c13.htm"></HEAD +><BODY +CLASS="BOOK" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="BOOK" +><A +NAME="LIBETPAN-README" +></A +><DIV +CLASS="TITLEPAGE" +><H1 +CLASS="TITLE" +><A +NAME="AEN2" +>libEtPan!</A +></H1 +><H3 +CLASS="AUTHOR" +><A +NAME="AEN6" +></A +>Viet Hoa DINH</H3 +><P +CLASS="COPYRIGHT" +>Copyright © 2003 DINH Viet Hoa</P +><HR></DIV +><DIV +CLASS="TOC" +><DL +><DT +><B +>Table of Contents</B +></DT +><DT +>1. <A +HREF="c13.htm" +>Introduction</A +></DT +><DD +><DL +><DT +><A +HREF="c13.htm#DESCRIPTION" +>Description</A +></DT +><DT +><A +HREF="x19.htm" +>Author</A +></DT +><DD +><DL +><DT +><A +HREF="x19.htm#MAIN-AUTH" +>Main author</A +></DT +><DT +><A +HREF="x19.htm#CONTRIB" +>Contributors</A +></DT +></DL +></DD +></DL +></DD +><DT +>2. <A +HREF="c53.htm" +>Installation</A +></DT +><DD +><DL +><DT +><A +HREF="c53.htm#DEPENDENCIES" +>Dependencies</A +></DT +><DD +><DL +><DT +><A +HREF="c53.htm#DEPEND-USERS" +>Dependencies for users</A +></DT +><DT +><A +HREF="c53.htm#DEPEND-DEVELOPERS" +>Dependencies for developers</A +></DT +></DL +></DD +><DT +><A +HREF="x82.htm" +>Existing packages</A +></DT +><DD +><DL +><DT +><A +HREF="x82.htm#PACKAGE-FREEBSD" +>FreeBSD</A +></DT +><DT +><A +HREF="x82.htm#PACKAGE-DEBIAN" +>Debian</A +></DT +><DT +><A +HREF="x82.htm#PACKAGE-MANDRAKE" +>Mandrake Linux</A +></DT +></DL +></DD +><DT +><A +HREF="x94.htm" +>Compilation</A +></DT +><DD +><DL +><DT +><A +HREF="x94.htm#COMPILE-FREEBSD" +>FreeBSD</A +></DT +><DT +><A +HREF="x94.htm#COMPILE-MACOSX" +>Mac OS X</A +></DT +><DT +><A +HREF="x94.htm#LINUX" +>Linux</A +></DT +><DT +><A +HREF="x94.htm#CONFIGURE" +>configure</A +></DT +><DT +><A +HREF="x94.htm#INSTALL" +>Compile and install</A +></DT +></DL +></DD +></DL +></DD +><DT +>3. <A +HREF="c157.htm" +>Use of libEtPan!</A +></DT +><DD +><DL +><DT +><A +HREF="c157.htm#HOTMAIL" +>How to open an Hotmail mailbox</A +></DT +></DL +></DD +></DL +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +> </TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +> </TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="c13.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +> </TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +> </TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Introduction</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/README/c13.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/README/c13.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,176 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Introduction</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan!" +HREF="book1.htm"><LINK +REL="PREVIOUS" +TITLE="libEtPan!" +HREF="book1.htm"><LINK +REL="NEXT" +TITLE="Author" +HREF="x19.htm"></HEAD +><BODY +CLASS="CHAPTER" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan!</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="book1.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +></TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x19.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="CHAPTER" +><H1 +><A +NAME="INTRODUCTION" +></A +>Chapter 1. Introduction</H1 +><DIV +CLASS="TOC" +><DL +><DT +><B +>Table of Contents</B +></DT +><DT +><A +HREF="c13.htm#DESCRIPTION" +>Description</A +></DT +><DT +><A +HREF="x19.htm" +>Author</A +></DT +></DL +></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="DESCRIPTION" +>Description</A +></H1 +><P +> The purpose of this mail library is to provide a portable, + efficient middleware for different kinds of mail access + (IMAPrev4, POP3, NNTP, mbox, MH, Maildir). + </P +><P +> You have two kinds of mailbox access, either using low-level + functions with a different interface for each kind of access + or using higher-level functions, using a driver to wrap the + higher-level API. The API will be the same for each kind of + mail access using the higher-level API. + </P +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x19.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>libEtPan!</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +> </TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Author</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/README/c157.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/README/c157.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,167 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Use of libEtPan!</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan!" +HREF="book1.htm"><LINK +REL="PREVIOUS" +TITLE="Compilation" +HREF="x94.htm"></HEAD +><BODY +CLASS="CHAPTER" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan!</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x94.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +></TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +> </TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="CHAPTER" +><H1 +><A +NAME="USE" +></A +>Chapter 3. Use of libEtPan!</H1 +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="HOTMAIL" +>How to open an Hotmail mailbox</A +></H1 +><P +> If you wish to access hotmail using libEtPan!, you can, by + using <A +HREF="http://hotwayd.sf.net" +TARGET="_top" +>hotwayd</A +>. + Then, create a POP3 storage with the given parameters : + command as clear text for connection type + (<B +CLASS="COMMAND" +>CONNECTION_TYPE_COMMAND</B +>), + <B +CLASS="COMMAND" +>"/usr/bin/hotwayd"</B +> + as command, plain text authentication + (<B +CLASS="COMMAND" +>ePOP3_AUTH_TYPE_PLAIN</B +>), + full hotmail address as login + (<B +CLASS="COMMAND" +>foobar@hotmail.com</B +> or + <B +CLASS="COMMAND" +>foobar@hotmail.com/mailbox_name</B +> if you want + to access a specific mailbox) and give your password. + </P +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x94.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +> </TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Compilation</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +> </TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +> </TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/README/c53.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/README/c53.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,258 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Installation</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan!" +HREF="book1.htm"><LINK +REL="PREVIOUS" +TITLE="Author" +HREF="x19.htm"><LINK +REL="NEXT" +TITLE="Existing packages" +HREF="x82.htm"></HEAD +><BODY +CLASS="CHAPTER" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan!</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x19.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +></TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x82.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="CHAPTER" +><H1 +><A +NAME="INSTALLATION" +></A +>Chapter 2. Installation</H1 +><DIV +CLASS="TOC" +><DL +><DT +><B +>Table of Contents</B +></DT +><DT +><A +HREF="c53.htm#DEPENDENCIES" +>Dependencies</A +></DT +><DT +><A +HREF="x82.htm" +>Existing packages</A +></DT +><DT +><A +HREF="x94.htm" +>Compilation</A +></DT +></DL +></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="DEPENDENCIES" +>Dependencies</A +></H1 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="DEPEND-USERS" +>Dependencies for users</A +></H2 +><P +></P +><UL +><LI +><P +> <A +HREF="http://www.openssl.org" +TARGET="_top" +>OpenSSL</A +> + (optional but recommended) + </P +></LI +><LI +><P +> <A +HREF="http://www.sleepycat.com" +TARGET="_top" +>Berkeley + DB</A +> (optional but recommended) + </P +></LI +><LI +><P +> POSIX Thread (required) + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="DEPEND-DEVELOPERS" +>Dependencies for developers</A +></H2 +><P +></P +><UL +><LI +><P +> <A +HREF="http://www.gnu.org/software/autoconf" +TARGET="_top" +> autoconf + </A +> + 2.13 + </P +></LI +><LI +><P +> <A +HREF="http://www.gnu.org/software/automake" +TARGET="_top" +> automake + </A +> + 1.4 + </P +></LI +><LI +><P +> <A +HREF="http://www.gnu.org/software/libtool/libtool.html" +TARGET="_top" +> libtool + </A +> + 1.4.3 + </P +></LI +><LI +><P +> jade and some SGML tools will be required + </P +></LI +></UL +></DIV +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x19.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x82.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Author</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +> </TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Existing packages</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/README/x19.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/README/x19.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,238 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Author</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan!" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Introduction" +HREF="c13.htm"><LINK +REL="PREVIOUS" +TITLE="Introduction" +HREF="c13.htm"><LINK +REL="NEXT" +TITLE="Installation" +HREF="c53.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan!</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="c13.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 1. Introduction</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="c53.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="AUTHOR" +>Author</A +></H1 +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="MAIN-AUTH" +>Main author</A +></H2 +><P +> DINH Viet Hoa <CODE +CLASS="EMAIL" +><<A +HREF="mailto:hoa@users.sourceforge.net" +>hoa@users.sourceforge.net</A +>></CODE +> + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CONTRIB" +>Contributors</A +></H2 +><P +> <P +></P +><UL +><LI +><P +> Wim Delvaux + </P +></LI +><LI +><P +> Melvin Hadasht + </P +></LI +><LI +><P +> David Woodhouse + </P +></LI +><LI +><P +> Juergen Graf + </P +></LI +><LI +><P +> Zsolt VARGA + </P +></LI +><LI +><P +> Gael Roualland + </P +></LI +><LI +><P +> Toni Willberg + </P +></LI +><LI +><P +> Rajko Albrecht + </P +></LI +><LI +><P +> Nikita V. Youshchenko + </P +></LI +><LI +><P +> Frederic Devernay + </P +></LI +><LI +><P +> Michael Leupold + </P +></LI +><LI +><P +> Colin Leroy + </P +></LI +></UL +> + </P +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="c13.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="c53.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Introduction</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c13.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Installation</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/README/x82.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/README/x82.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,184 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Existing packages</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan!" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Installation" +HREF="c53.htm"><LINK +REL="PREVIOUS" +TITLE="Installation" +HREF="c53.htm"><LINK +REL="NEXT" +TITLE="Compilation" +HREF="x94.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan!</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="c53.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 2. Installation</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="x94.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="PACKAGES" +>Existing packages</A +></H1 +><P +> Before you try to compile it, you have to know that packages + exist for some systems. + </P +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="PACKAGE-FREEBSD" +>FreeBSD</A +></H2 +><P +> you can find it in ports/mail/libetpan. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="PACKAGE-DEBIAN" +>Debian</A +></H2 +><P +> This is in the package collection. + </P +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="PACKAGE-MANDRAKE" +>Mandrake Linux</A +></H2 +><P +> This is in the package collection. + </P +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="c53.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="x94.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Installation</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c53.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Compilation</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/README/x94.htm ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/README/x94.htm Wed Dec 20 15:28:56 2006 @@ -0,0 +1,394 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> +<HTML +><HEAD +><TITLE +>Compilation</TITLE +><META +NAME="GENERATOR" +CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK +REL="HOME" +TITLE="libEtPan!" +HREF="book1.htm"><LINK +REL="UP" +TITLE="Installation" +HREF="c53.htm"><LINK +REL="PREVIOUS" +TITLE="Existing packages" +HREF="x82.htm"><LINK +REL="NEXT" +TITLE="Use of libEtPan!" +HREF="c157.htm"></HEAD +><BODY +CLASS="SECT1" +BGCOLOR="#FFFFFF" +TEXT="#000000" +LINK="#0000FF" +VLINK="#840084" +ALINK="#0000FF" +><DIV +CLASS="NAVHEADER" +><TABLE +SUMMARY="Header navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TH +COLSPAN="3" +ALIGN="center" +>libEtPan!</TH +></TR +><TR +><TD +WIDTH="10%" +ALIGN="left" +VALIGN="bottom" +><A +HREF="x82.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="80%" +ALIGN="center" +VALIGN="bottom" +>Chapter 2. Installation</TD +><TD +WIDTH="10%" +ALIGN="right" +VALIGN="bottom" +><A +HREF="c157.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +></TABLE +><HR +ALIGN="LEFT" +WIDTH="100%"></DIV +><DIV +CLASS="SECT1" +><H1 +CLASS="SECT1" +><A +NAME="COMPILATION" +>Compilation</A +></H1 +><P +> Generic installation instructions are in the + <TT +CLASS="FILENAME" +>INSTALL</TT +> file + You can pass the following extra options to configure : + </P +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="COMPILE-FREEBSD" +>FreeBSD</A +></H2 +><P +></P +><UL +><LI +><P +> make sure libiconv is installed from the ports collection (see + <B +CLASS="COMMAND" +>pkg_info</B +>). + </P +></LI +><LI +><P +> issue configure with the following parameter: + <PRE +CLASS="SCREEN" +><SAMP +CLASS="PROMPT" +>$</SAMP +> <KBD +CLASS="USERINPUT" +>./configure --with-libiconv-prefix=/usr/local</KBD +> + </PRE +> + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="COMPILE-MACOSX" +>Mac OS X</A +></H2 +><P +></P +><UL +><LI +><P +> in tests/option-parser.c, change the inclusion + of <TT +CLASS="FILENAME" +>getopt.h</TT +> to + <TT +CLASS="FILENAME" +>gnugetopt/getopt.h</TT +> + </P +></LI +><LI +><P +> in <TT +CLASS="FILENAME" +>tests/Makefile</TT +>, add + <B +CLASS="COMMAND" +>-I/sw/include</B +> for the + <B +CLASS="COMMAND" +>CFLAGS</B +> and + -L/sw/lib -lgnugetopt for the LDFLAGS. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="LINUX" +>Linux</A +></H2 +><P +></P +><UL +><LI +><DIV +CLASS="WARNING" +><P +></P +><TABLE +CLASS="WARNING" +BORDER="1" +WIDTH="90%" +><TR +><TD +ALIGN="CENTER" +><B +>Warning</B +></TD +></TR +><TR +><TD +ALIGN="LEFT" +><P +> Since libEtPan! is making high usage of + <B +CLASS="COMMAND" +>mmap()</B +> even for + writing, when your mailboxes are on + <B +CLASS="COMMAND" +>NFS</B +> filesystem with + a Linux server, it is advised to use option + <B +CLASS="COMMAND" +>no_subtree_check</B +> in + <TT +CLASS="FILENAME" +>/etc/exports</TT +>. + This should avoid corruption of data. + </P +><P +> The problem exist in Linux 2.4.22 and earlier versions. + </P +></TD +></TR +></TABLE +></DIV +></LI +><LI +><P +> On RedHat systems, you have to configure using the + following command line : + <B +CLASS="COMMAND" +>./configure --with-openssl=/usr/kerberos</B +> + </P +></LI +><LI +><P +> On Debian systems, if the <B +CLASS="COMMAND" +>./autogen</B +> + script fails on missing <B +CLASS="COMMAND" +>AM_ICONV</B +>, you + have to install <B +CLASS="COMMAND" +>gettext</B +> package. + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="CONFIGURE" +>configure</A +></H2 +><P +> You can use the following options : + </P +><P +></P +><UL +><LI +><P +> <B +CLASS="COMMAND" +>--enable-debug</B +> Compiles with + debugging turned on + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>--enable-optim</B +> Turns on some + optimizations flags for gcc + </P +></LI +><LI +><P +> <B +CLASS="COMMAND" +>--without-openssl</B +> Disables OpenSSL (do + not look for it) + </P +></LI +></UL +></DIV +><DIV +CLASS="SECT2" +><H2 +CLASS="SECT2" +><A +NAME="INSTALL" +>Compile and install</A +></H2 +><P +> Download the package and do the following : + </P +><PRE +CLASS="PROGRAMLISTING" +>$ tar xzvf libetpan-XX.XX.tar.gz # to decompress the package + +$ cd libetpan-XX.XX + +$ ./configure --help # to get options of configure + +$ ./configure # you can specify your own options + +$ make # to compile the package + +$ su + +# make install + +# logout + </PRE +></DIV +></DIV +><DIV +CLASS="NAVFOOTER" +><HR +ALIGN="LEFT" +WIDTH="100%"><TABLE +SUMMARY="Footer navigation table" +WIDTH="100%" +BORDER="0" +CELLPADDING="0" +CELLSPACING="0" +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +><A +HREF="x82.htm" +ACCESSKEY="P" +>Prev</A +></TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="book1.htm" +ACCESSKEY="H" +>Home</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +><A +HREF="c157.htm" +ACCESSKEY="N" +>Next</A +></TD +></TR +><TR +><TD +WIDTH="33%" +ALIGN="left" +VALIGN="top" +>Existing packages</TD +><TD +WIDTH="34%" +ALIGN="center" +VALIGN="top" +><A +HREF="c53.htm" +ACCESSKEY="U" +>Up</A +></TD +><TD +WIDTH="33%" +ALIGN="right" +VALIGN="top" +>Use of libEtPan!</TD +></TR +></TABLE +></DIV +></BODY +></HTML +> \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/doc/depend.dot ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/depend.dot Wed Dec 20 15:28:56 2006 @@ -0,0 +1,54 @@ +digraph "etPan! library" { + mime -> imf; + + "session/message" -> imf; + "session/message" -> mime; + + "storage/folder" -> "session/message"; +} + +digraph "imap driver" { + "imap driver" -> imap; + "imap driver" -> imf; + "imap driver" -> mime; + "imap driver" -> "session/message"; + + mime -> imf; +} + +digraph "mbox driver" { + "mbox driver" -> mbox; + "mbox driver" -> imf; + "mbox driver" -> mime; + "mbox driver" -> "session/message"; + "mbox" -> imf; + + mime -> imf; +} + +digraph "mh driver" { + "mh driver" -> mh; + "mh driver" -> imf; + "mh driver" -> mime; + "mh driver" -> "session/message"; + + mime -> imf; +} + +digraph "pop3 driver" { + "pop3 driver" -> pop3; + "pop3 driver" -> imf; + "pop3 driver" -> mime; + "pop3 driver" -> "session/message"; + + mime -> imf; +} + +digraph "nntp driver" { + "nntp driver" -> nntp; + "nntp driver" -> imf; + "nntp driver" -> mime; + "nntp driver" -> "session/message"; + + mime -> imf; +} Added: freeswitch/trunk/libs/libetpan/doc/layer.fig ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/doc/layer.fig Wed Dec 20 15:28:56 2006 @@ -0,0 +1,39 @@ +#FIG 3.2 +Landscape +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 900 3150 12150 3150 12150 3825 900 3825 900 3150 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 900 3825 12150 3825 12150 4500 900 4500 900 3825 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 3150 3150 3150 3825 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 5400 3150 5400 3825 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 7650 3150 7650 3825 +2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 9900 3150 9900 3825 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 7 + 12150 3150 900 3150 900 2475 12825 2475 12825 4500 12150 4500 + 12150 3150 +2 3 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 7 + 900 2475 900 1800 13500 1800 13500 4500 12825 4500 12825 2475 + 900 2475 +2 3 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 8 + 900 4500 225 4500 225 1125 13500 1125 13500 1800 900 1800 + 900 4500 900 4500 +4 0 0 50 0 16 20 0.0000 4 210 1410 1305 3600 IMAP4rev1\001 +4 0 0 50 0 16 20 0.0000 4 210 450 10800 3600 MH\001 +4 0 0 50 0 16 20 0.0000 4 210 720 8370 3555 mbox\001 +4 0 0 50 0 16 20 0.0000 4 210 795 6120 3600 NNTP\001 +4 0 0 50 0 16 20 0.0000 4 210 765 3870 3600 POP3\001 +4 0 0 50 0 16 20 0.0000 4 270 1620 5670 2880 session layer\001 +4 0 0 50 0 16 20 0.0000 4 270 2730 5085 2250 storage / folders layer\001 +4 0 0 50 0 16 20 0.0000 4 210 1500 5760 4275 IMF / MIME\001 +4 0 0 50 0 16 20 0.0000 4 270 1395 5670 1575 application\001 Added: freeswitch/trunk/libs/libetpan/install-sh ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/install-sh Wed Dec 20 15:28:56 2006 @@ -0,0 +1,442 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2006-05-11.20 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +posix_glob= +posix_mkdir= + +# Symbolic mode for testing mkdir with directories. +# It is the same as 755, but also tests that "u+" works. +test_mode=u=rwx,g=rx,o=rx,u+wx + +# Desired mode of installed file. +mode=0755 + +# Desired mode of newly created intermediate directories. +# It is empty if not known yet. +intermediate_mode= + +chmodcmd=$chmodprog +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac +done + +if test $# -ne 0 && test -z "$dir_arg$dstarg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +test -n "$dir_arg" || trap '(exit $?); exit' 1 2 13 15 + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + posix_mkdir=false + if $mkdirprog -m $test_mode -p -- / >/dev/null 2>&1; then + posix_mkdir=true + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./-m "$test_mode" ./-p ./-- 2>/dev/null + fi ;; + esac + + if + $posix_mkdir && { + + # With -d, create the new directory with the user-specified mode. + # Otherwise, create it using the same intermediate mode that + # mkdir -p would use when creating intermediate directories. + # POSIX says that this mode is "$(umask -S),u+wx", so use that + # if umask -S works. + + if test -n "$dir_arg"; then + mkdir_mode=$mode + else + case $intermediate_mode in + '') + if umask_S=`(umask -S) 2>/dev/null`; then + intermediate_mode=$umask_S,u+wx + else + intermediate_mode=$test_mode + fi ;; + esac + mkdir_mode=$intermediate_mode + fi + + $mkdirprog -m "$mkdir_mode" -p -- "$dstdir" + } + then : + else + + # mkdir does not conform to POSIX, or it failed possibly due to + # a race condition. Create the directory the slow way, step by + # step, checking for races as we go. + + case $dstdir in + /*) prefix=/ ;; + -*) prefix=./ ;; + *) prefix= ;; + esac + + case $posix_glob in + '') + if (set -f) 2>/dev/null; then + posix_glob=true + else + posix_glob=false + fi ;; + esac + + oIFS=$IFS + IFS=/ + $posix_glob && set -f + set fnord $dstdir + shift + $posix_glob && set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + $mkdirprog -m "$mkdir_mode" -p -- "$dstdir" && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + eval "\$mkdirprog $prefixes" || test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd "$mode" "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$mode" "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dst"; then + $doit $rmcmd -f "$dst" 2>/dev/null \ + || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \ + && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\ + || { + echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + } || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: Added: freeswitch/trunk/libs/libetpan/libetpan-config.h.in ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/libetpan-config.h.in Wed Dec 20 15:28:56 2006 @@ -0,0 +1,38 @@ +@ifndef LIBETPAN_CONFIG_H + +@define LIBETPAN_CONFIG_H + +#ifndef CONFIG_H +#define CONFIG_H +#include "config.h" +#endif +@ifdef _MSC_VER +@ define MMAP_UNAVAILABLE +@ define inline __inline +@endif +#ifdef HAVE_LIMITS_H +@include <limits.h> +#endif +#ifdef HAVE_SYS_PARAM_H +/* support for ARM platforms with a 2.95.3 arm-gcc suite */ +@include <sys/param.h> +#endif +#if HAVE_INTTYPES_H +@include <inttypes.h> +#endif + +@define MAIL_DIR_SEPARATOR '/' + +@define MAIL_DIR_SEPARATOR_S "/" + +@ifdef _MSC_VER +@ ifdef LIBETPAN_DLL +@ define LIBETPAN_EXPORT __declspec(dllexport) +@ else +@ define LIBETPAN_EXPORT __declspec(dllimport) +@ endif +@else +@ define LIBETPAN_EXPORT +@endif + +@endif Added: freeswitch/trunk/libs/libetpan/libetpan-config.in ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/libetpan-config.in Wed Dec 20 15:28:56 2006 @@ -0,0 +1,60 @@ +#!/bin/sh + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +exec_prefix_set=no + +usage="\ +Usage: libetpan-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--libs] [--cflags]" + +if test $# -eq 0; then + echo "${usage}" 1>&2 + exit 1 +fi + +while test $# -gt 0; do + case "$1" in + -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + case $1 in + --prefix=*) + prefix=$optarg + if test $exec_prefix_set = no ; then + exec_prefix=$optarg + fi + ;; + --prefix) + echo $prefix + ;; + --exec-prefix=*) + exec_prefix=$optarg + exec_prefix_set=yes + ;; + --exec-prefix) + echo $exec_prefix + ;; + --version) + echo @VERSION@ + ;; + --cflags) + if test "@includedir@" = "/usr/include" ; then + includedir="" + else + includedir=-I@includedir@ + fi + echo $includedir + ;; + --libs) + libdir=-L@libdir@ + echo $libdir -letpan@LIBSUFFIX@ @LDFLAGS@ @SSLLIBS@ @GNUTLSLIB@ @LIBICONV@ @DBLIB@ @LIBS@ @SASLLIBS@ + ;; + *) + echo "${usage}" 1>&2 + exit 1 + ;; + esac + shift +done + Added: freeswitch/trunk/libs/libetpan/ltmain.sh ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/ltmain.sh Wed Dec 20 15:28:56 2006 @@ -0,0 +1,6871 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun configure. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 +# Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +basename="s,^.*/,,g" + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + +# The name of this program: +progname=`echo "$progpath" | $SED $basename` +modename="$progname" + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION="1.5.22 Debian 1.5.22-4" +TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)" + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes. +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +# Check that we have a working $echo. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell, and then maybe $echo will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <<EOF +$* +EOF + exit $EXIT_SUCCESS +fi + +default_mode= +help="Try \`$progname --help' for more information." +magic="%%%MAGIC variable%%%" +mkdir="mkdir" +mv="mv -f" +rm="rm -f" + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g' +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + SP2NL='tr \040 \012' + NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + SP2NL='tr \100 \n' + NL2SP='tr \r\n \100\100' + ;; +esac + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +# We save the old values to restore during execute mode. +if test "${LC_ALL+set}" = set; then + save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL +fi +if test "${LANG+set}" = set; then + save_LANG="$LANG"; LANG=C; export LANG +fi + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + $echo "$modename: not configured to build any kind of library" 1>&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +duplicate_deps=no +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +##################################### +# Shell function definitions: +# This seems to be the best place for them + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $mkdir "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || { + $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2 + exit $EXIT_FAILURE + } + fi + + $echo "X$my_tmpdir" | $Xsed +} + + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +func_win32_libid () +{ + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ + $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | \ + $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $echo $win32_libid_type +} + + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case "$@ " in + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + $echo "$modename: unable to infer tagged configuration" + $echo "$modename: specify a tag with \`--tag'" 1>&2 + exit $EXIT_FAILURE +# else +# $echo "$modename: using $tagname tagged configuration" + fi + ;; + esac + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + + $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)" + $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $? + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2 + exit $EXIT_FAILURE + fi +} + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + my_status="" + + $show "${rm}r $my_gentop" + $run ${rm}r "$my_gentop" + $show "$mkdir $my_gentop" + $run $mkdir "$my_gentop" + my_status=$? + if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then + exit $my_status + fi + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` + my_xdir="$my_gentop/$my_xlib" + + $show "${rm}r $my_xdir" + $run ${rm}r "$my_xdir" + $show "$mkdir $my_xdir" + $run $mkdir "$my_xdir" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then + exit $exit_status + fi + case $host in + *-darwin*) + $show "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + if test -z "$run"; then + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'` + darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null` + if test -n "$darwin_arches"; then + darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + $show "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we have a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + lipo -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + ${rm}r unfat-$$ + cd "$darwin_orig_dir" + else + cd "$darwin_orig_dir" + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + fi # $run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + func_extract_archives_result="$my_oldobjs" +} +# End of Shell function definitions +##################################### + +# Darwin sucks +eval std_shrext=\"$shrext_cmds\" + +disable_libs=no + +# Parse our command line options once, thoroughly. +while test "$#" -gt 0 +do + arg="$1" + shift + + case $arg in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + execute_dlfiles) + execute_dlfiles="$execute_dlfiles $arg" + ;; + tag) + tagname="$arg" + preserve_args="${preserve_args}=$arg" + + # Check whether tagname contains only valid characters + case $tagname in + *[!-_A-Za-z0-9,/]*) + $echo "$progname: invalid tag name: $tagname" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $tagname in + CC) + # Don't test for the "default" C tag, as we know, it's there, but + # not specially marked. + ;; + *) + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then + taglist="$taglist $tagname" + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`" + else + $echo "$progname: ignoring unknown tag $tagname" 1>&2 + fi + ;; + esac + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case $arg in + --help) + show_help=yes + ;; + + --version) + $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" + $echo + $echo "Copyright (C) 2005 Free Software Foundation, Inc." + $echo "This is free software; see the source for copying conditions. There is NO" + $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + exit $? + ;; + + --config) + ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath + # Now print the configurations for the tags. + for tagname in $taglist; do + ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath" + done + exit $? + ;; + + --debug) + $echo "$progname: enabling shell trace mode" + set -x + preserve_args="$preserve_args $arg" + ;; + + --dry-run | -n) + run=: + ;; + + --features) + $echo "host: $host" + if test "$build_libtool_libs" = yes; then + $echo "enable shared libraries" + else + $echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + $echo "enable static libraries" + else + $echo "disable static libraries" + fi + exit $? + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --preserve-dup-deps) duplicate_deps="yes" ;; + + --quiet | --silent) + show=: + preserve_args="$preserve_args $arg" + ;; + + --tag) + prevopt="--tag" + prev=tag + preserve_args="$preserve_args --tag" + ;; + --tag=*) + set tag "$optarg" ${1+"$@"} + shift + prev=tag + preserve_args="$preserve_args --tag" + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE +fi + +case $disable_libs in +no) + ;; +shared) + build_libtool_libs=no + build_old_libs=yes + ;; +static) + build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` + ;; +esac + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 + $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2 + case $nonopt in + *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) + mode=link + for arg + do + case $arg in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case $mode in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + if test -n "$libobj" ; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit $EXIT_FAILURE + fi + arg_mode=target + continue + ;; + + -static | -prefer-pic | -prefer-non-pic) + later="$later $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + lastarg="$lastarg $arg" + done + IFS="$save_ifs" + lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` + + # Add the arguments to base_compile. + base_compile="$base_compile $lastarg" + continue + ;; + + * ) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + case $lastarg in + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, and some SunOS ksh mistreat backslash-escaping + # in scan sets (worked around with variable expansion), + # and furthermore cannot handle '|' '&' '(' ')' in scan sets + # at all, so we specify them separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + lastarg="\"$lastarg\"" + ;; + esac + + base_compile="$base_compile $lastarg" + done # for arg + + case $arg_mode in + arg) + $echo "$modename: you must specify an argument for -Xcompile" + exit $EXIT_FAILURE + ;; + target) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit $EXIT_FAILURE + ;; + *) + # Get the name of the library object. + [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSifmso]' + case $libobj in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.ii) xform=ii ;; + *.class) xform=class ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + *.java) xform=java ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case $libobj in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -static) + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"` + case $qlibobj in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qlibobj="\"$qlibobj\"" ;; + esac + test "X$libobj" != "X$qlibobj" \ + && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && $echo "$modename: libobj name \`$libobj' may not contain shell special characters." + objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir= + else + xdir=$xdir/ + fi + lobj=${xdir}$objdir/$objname + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + $run $rm $removelist + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $run ln "$progpath" "$lockfile" 2>/dev/null; do + $show "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $echo "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + $echo "$srcfile" > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"` + case $qsrcfile in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qsrcfile="\"$qsrcfile\"" ;; + esac + + $run $rm "$libobj" "${libobj}T" + + # Create a libtool object file (analogous to a ".la" file), + # but don't create it if we're doing a dry run. + test -z "$run" && cat > ${libobj}T <<EOF +# $libobj - a libtool object file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +EOF + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + if test ! -d "${xdir}$objdir"; then + $show "$mkdir ${xdir}$objdir" + $run $mkdir ${xdir}$objdir + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "${xdir}$objdir"; then + exit $exit_status + fi + fi + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + command="$command -o $lobj" + fi + + $run $rm "$lobj" "$output_obj" + + $show "$command" + if $run eval "$command"; then : + else + test -n "$output_obj" && $run $rm $removelist + exit $EXIT_FAILURE + fi + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + $show "$mv $output_obj $lobj" + if $run $mv $output_obj $lobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the PIC object to the libtool object file. + test -z "$run" && cat >> ${libobj}T <<EOF +pic_object='$objdir/$objname' + +EOF + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + else + # No PIC object so indicate it doesn't exist in the libtool + # object file. + test -z "$run" && cat >> ${libobj}T <<EOF +pic_object=none + +EOF + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + command="$command -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + command="$command$suppress_output" + $run $rm "$obj" "$output_obj" + $show "$command" + if $run eval "$command"; then : + else + $run $rm $removelist + exit $EXIT_FAILURE + fi + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the non-PIC object the libtool object file. + # Only append if the libtool object file exists. + test -z "$run" && cat >> ${libobj}T <<EOF +# Name of the non-PIC object. +non_pic_object='$objname' + +EOF + else + # Append the name of the non-PIC object the libtool object file. + # Only append if the libtool object file exists. + test -z "$run" && cat >> ${libobj}T <<EOF +# Name of the non-PIC object. +non_pic_object=none + +EOF + fi + + $run $mv "${libobj}T" "${libobj}" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + $run $rm "$lockfile" + fi + + exit $EXIT_SUCCESS + ;; + + # libtool link mode + link | relink) + modename="$modename: link" + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args="$nonopt" + base_compile="$nonopt $@" + compile_command="$nonopt" + finalize_command="$nonopt" + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + + avoid_version=no + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + notinst_path= # paths that contain not-installed libtool libraries + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -all-static | -static) + if test "X$arg" = "X-all-static"; then + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + else + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + fi + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test + ;; + *) qarg=$arg ;; + esac + libtool_args="$libtool_args $qarg" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit $EXIT_FAILURE + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat $save_arg` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + done + else + $echo "$modename: link input file \`$save_arg' does not exist" + exit $EXIT_FAILURE + fi + arg=$save_arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + compile_command="$compile_command $wl$qarg" + finalize_command="$finalize_command $wl$qarg" + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + darwin_framework|darwin_framework_skip) + test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + prev= + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: more than one -exported-symbols argument is not allowed" + exit $EXIT_FAILURE + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework|-arch|-isysroot) + case " $CC " in + *" ${arg} ${1} "* | *" ${arg} ${1} "*) + prev=darwin_framework_skip ;; + *) compiler_flags="$compiler_flags $arg" + prev=darwin_framework ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + ;; + esac + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + notinst_path="$notinst_path $dir" + fi + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + deplibs="$deplibs -framework System" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + -model) + compile_command="$compile_command $arg" + compiler_flags="$compiler_flags $arg" + finalize_command="$finalize_command $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m* pass through architecture-specific compiler args for GCC + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -pg pass through profiling flag for GCC + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \ + -t[45]*|-txscale*|@*) + + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + compiler_flags="$compiler_flags $arg" + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # The PATH hackery in wrapper scripts is required on Windows + # in order for the loader to find any dlls it needs. + $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 + $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Wl,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $wl$flag" + linker_flags="$linker_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done # argument parsing loop + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + # Create the object directory. + if test ! -d "$output_objdir"; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then + exit $exit_status + fi + fi + + # Determine the type of output + case $output in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + case $host in + *cygwin* | *mingw* | *pw32*) + # don't eliminate duplications in $postdeps and $predeps + duplicate_compiler_generated_deps=yes + ;; + *) + duplicate_compiler_generated_deps=$duplicate_deps + ;; + esac + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if test "X$duplicate_deps" = "Xyes" ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$pre_post_deps $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + case $linkmode in + lib) + passes="conv link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + for pass in $passes; do + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; + esac + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + compiler_flags="$compiler_flags $deplib" + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 + continue + fi + name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` + for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if (${SED} -e '2q' $lib | + grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + library_names= + old_library= + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + *) + $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + if eval $echo \"$deplib\" 2>/dev/null \ + | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + $echo + $echo "*** Warning: Trying to link with static lib archive $deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because the file extensions .$libext of this argument makes me believe" + $echo "*** that it is just a static archive that I should not used here." + else + $echo + $echo "*** Warning: Linking the shared library $output against the" + $echo "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + if test "$found" = yes || test -f "$lib"; then : + else + $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2 + exit $EXIT_FAILURE + fi + + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + $echo "$modename: \`$lib' is not a convenience library" 1>&2 + exit $EXIT_FAILURE + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + abs_ladir="$ladir" + fi + ;; + esac + laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + $echo "$modename: warning: library \`$lib' was moved." 1>&2 + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi + fi # $installed = yes + name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *" $absdir "*) ;; + *) temp_rpath="$temp_rpath $absdir" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes ; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + # This is a shared library + + # Warn about portability, can't link against -module's on + # some systems (darwin) + if test "$shouldnotlink" = yes && test "$pass" = link ; then + $echo + if test "$linkmode" = prog; then + $echo "*** Warning: Linking the executable $output against the loadable module" + else + $echo "*** Warning: Linking the shared library $output against the loadable module" + fi + $echo "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + realname="$2" + shift; shift + libname=`eval \\$echo \"$libname_spec\"` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw*) + major=`expr $current - $age` + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + soname=`$echo $soroot | ${SED} -e 's/^.*\///'` + newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + $show "extracting exported symbol list from \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$extract_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + $show "generating import library for \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$old_archive_from_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a module then we can not link against + # it, someone is ignoring the new warnings I added + if /usr/bin/file -L $add 2> /dev/null | + $EGREP ": [^:]* bundle" >/dev/null ; then + $echo "** Warning, lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + $echo + $echo "** And there doesn't seem to be a static archive available" + $echo "** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + $echo "$modename: configuration error: unsupported hardcode properties" + exit $EXIT_FAILURE + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && \ + test "$hardcode_minus_L" != yes && \ + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + $echo + $echo "*** Warning: This system can not link to static lib archive $lib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + $echo "*** But as you try to build a module library, libtool will still create " + $echo "*** a static module, that should work as long as the dlopening application" + $echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + case $deplib in + -L*) path="$deplib" ;; + *.la) + dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$deplib" && dir="." + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + fi + ;; + esac + if grep "^installed=no" $deplib > /dev/null; then + path="$absdir/$objdir" + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + if test "$absdir" != "$libdir"; then + $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 + fi + path="$absdir" + fi + depdepl= + case $host in + *-*-darwin*) + # we do not want to link against static libs, + # but need to link against shared + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$path/$depdepl" ; then + depdepl="$path/$depdepl" + fi + # do not add paths which are already there + case " $newlib_search_path " in + *" $path "*) ;; + *) newlib_search_path="$newlib_search_path $path";; + esac + fi + path="" + ;; + *) + path="-L$path" + ;; + esac + ;; + -l*) + case $host in + *-*-darwin*) + # Again, we only want to link against shared libraries + eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` + for tmp in $newlib_search_path ; do + if test -f "$tmp/lib$tmp_libs.dylib" ; then + eval depdepl="$tmp/lib$tmp_libs.dylib" + break + fi + done + path="" + ;; + *) continue ;; + esac + ;; + *) continue ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + case " $deplibs " in + *" $depdepl "*) ;; + *) deplibs="$depdepl $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 + exit $EXIT_FAILURE + else + $echo + $echo "*** Warning: Linking the shared library $output against the non-libtool" + $echo "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + if test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test "$#" -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$2" + number_minor="$3" + number_revision="$4" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows) + current=`expr $number_major + $number_minor` + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + current=`expr $number_major + $number_minor - 1` + age="$number_minor" + revision="$number_minor" + ;; + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE + ;; + esac + ;; + no) + current="$2" + revision="$3" + age="$4" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test "$age" -gt "$current"; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + minor_current=`expr $current + 1` + verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + irix | nonstopux) + major=`expr $current - $age + 1` + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=.`expr $current - $age` + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + major=`expr $current - $age` + versuffix="-$major" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + fi + + if test "$mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$echo "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + removelist="$removelist $p" + ;; + *) ;; + esac + done + if test -n "$removelist"; then + $show "${rm}r $removelist" + $run ${rm}r $removelist + fi + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + for path in $notinst_path; do + lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` + deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` + dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` + done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs -framework System" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $rm conftest.c + cat > conftest.c <<EOF + int main() { return 0; } +EOF + $rm conftest + $LTCC $LTCFLAGS -o conftest conftest.c $deplibs + if test "$?" -eq 0 ; then + ldd_output=`ldd conftest` + for i in $deplibs; do + name=`expr $i : '-l\(.*\)'` + # If $name is empty we are operating on a -L argument. + if test "$name" != "" && test "$name" -ne "0"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $i "*) + newdeplibs="$newdeplibs $i" + i="" + ;; + esac + fi + if test -n "$i" ; then + libname=`eval \\$echo \"$libname_spec\"` + deplib_matches=`eval \\$echo \"$library_names_spec\"` + set dummy $deplib_matches + deplib_match=$2 + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then + newdeplibs="$newdeplibs $i" + else + droppeddeps=yes + $echo + $echo "*** Warning: dynamic linker does not accept needed library $i." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which I believe you do not have" + $echo "*** because a test_compile did reveal that the linker did not use it for" + $echo "*** its dynamic dependency list that programs get resolved with at runtime." + fi + fi + else + newdeplibs="$newdeplibs $i" + fi + done + else + # Error occurred in the first compile. Let's try to salvage + # the situation: Compile a separate program for each library. + for i in $deplibs; do + name=`expr $i : '-l\(.*\)'` + # If $name is empty we are operating on a -L argument. + if test "$name" != "" && test "$name" != "0"; then + $rm conftest + $LTCC $LTCFLAGS -o conftest conftest.c $i + # Did it work? + if test "$?" -eq 0 ; then + ldd_output=`ldd conftest` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $i "*) + newdeplibs="$newdeplibs $i" + i="" + ;; + esac + fi + if test -n "$i" ; then + libname=`eval \\$echo \"$libname_spec\"` + deplib_matches=`eval \\$echo \"$library_names_spec\"` + set dummy $deplib_matches + deplib_match=$2 + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then + newdeplibs="$newdeplibs $i" + else + droppeddeps=yes + $echo + $echo "*** Warning: dynamic linker does not accept needed library $i." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because a test_compile did reveal that the linker did not use this one" + $echo "*** as a dynamic dependency that programs can get resolved with at runtime." + fi + fi + else + droppeddeps=yes + $echo + $echo "*** Warning! Library $i is needed by this library but I was not able to" + $echo "*** make it link in! You will probably need to install it or some" + $echo "*** library that it depends on before this library will be fully" + $echo "*** functional. Installing it before continuing would be even better." + fi + else + newdeplibs="$newdeplibs $i" + fi + done + fi + ;; + file_magic*) + set dummy $deplibs_check_method + file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + for a_deplib in $deplibs; do + name=`expr $a_deplib : '-l\(.*\)'` + # If $name is empty we are operating on a -L argument. + if test "$name" != "" && test "$name" != "0"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval \\$echo \"$libname_spec\"` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null \ + | grep " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for file magic test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a file magic. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + for a_deplib in $deplibs; do + name=`expr $a_deplib : '-l\(.*\)'` + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval \\$echo \"$libname_spec\"` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval $echo \"$potent_lib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a regex pattern. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e 's/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` + done + fi + if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ + | grep . >/dev/null; then + $echo + if test "X$deplibs_check_method" = "Xnone"; then + $echo "*** Warning: inter-library dependencies are not supported in this platform." + else + $echo "*** Warning: inter-library dependencies are not known to be supported." + fi + $echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + $echo + $echo "*** Warning: libtool could not satisfy all declared inter-library" + $echo "*** dependencies of module $libname. Therefore, libtool will create" + $echo "*** a static module, that should work as long as the dlopening" + $echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + $echo "*** The inter-library dependencies that have been dropped here will be" + $echo "*** automatically added whenever a program is linked with this library" + $echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + $echo + $echo "*** Since this library must not contain undefined symbols," + $echo "*** because either the platform does not support them or" + $echo "*** it was explicitly requested with -no-undefined," + $echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + deplibs="$new_libs" + + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + if len=`expr "X$cmd" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + $show "$cmd" + $run eval "$cmd" || exit $? + skipped_export=false + else + # The command line is too long to execute in one step. + $show "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex"; then + $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise. + $echo "creating reloadable object files..." + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + output_la=`$echo "X$output" | $Xsed -e "$basename"` + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + delfiles= + last_robj= + k=1 + output=$output_objdir/$output_la-${k}.$objext + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + eval test_cmds=\"$reload_cmds $objlist $last_robj\" + if test "X$objlist" = X || + { len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; }; then + objlist="$objlist $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + k=`expr $k + 1` + output=$output_objdir/$output_la-${k}.$objext + objlist=$obj + len=1 + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + + if ${skipped_export-false}; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + libobjs=$output + # Append the command to create the export file. + eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" + fi + + # Set up a command to remove the reloadable object files + # after they are used. + i=0 + while test "$i" -lt "$k" + do + i=`expr $i + 1` + delfiles="$delfiles $output_objdir/$output_la-${i}.$objext" + done + + $echo "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + + # Append the command to remove the reloadable object files + # to the just-reset $cmds. + eval cmds=\"\$cmds~\$rm $delfiles\" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case $output in + *.lo) + if test -n "$objs$old_deplibs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit $EXIT_FAILURE + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${obj}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $run eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; + esac + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + case $host in + *darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + if test "$tagname" = CXX ; then + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + fi + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case $dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $run $rm $export_symbols + $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + else + $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` + $run eval '$echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $mv "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if grep -v "^: " < "$nlist" | + if sort -k 3 </dev/null >/dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + grep -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' + else + $echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr void * +#else +# define lt_ptr char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +" + + case $host in + *cygwin* | *mingw* ) + $echo >> "$output_objdir/$dlsyms" "\ +/* DATA imports from DLLs on WIN32 can't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs */ +struct { +" + ;; + * ) + $echo >> "$output_objdir/$dlsyms" "\ +const struct { +" + ;; + esac + + + $echo >> "$output_objdir/$dlsyms" "\ + const char *name; + lt_ptr address; +} +lt_preloaded_symbols[] = +{\ +" + + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; + esac;; + *-*-hpux*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + case $host in + *cygwin* | *mingw* ) + if test -f "$output_objdir/${outputname}.def" ; then + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + else + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + fi + ;; + * ) + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + esac + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + exit_status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $exit_status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $run $rm $output + # Link the executable and exit + $show "$link_command" + $run eval "$link_command" || exit $? + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + output_name=`basename $output` + output_path=`dirname $output` + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $rm $cwrappersource $cwrapper + trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + cat > $cwrappersource <<EOF + +/* $cwrappersource - temporary wrapper executable for $objdir/$outputname + Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP + + The $output program cannot be directly executed until all the libtool + libraries that it depends on are installed. + + This wrapper executable should never be moved out of the build directory. + If it is, it will not operate correctly. + + Currently, it simply execs the wrapper *script* "/bin/sh $output", + but could eventually absorb all of the scripts functionality and + exec $objdir/$outputname directly. +*/ +EOF + cat >> $cwrappersource<<"EOF" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <malloc.h> +#include <stdarg.h> +#include <assert.h> +#include <string.h> +#include <ctype.h> +#include <sys/stat.h> + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +/* -DDEBUG is fairly common in CFLAGS. */ +#undef DEBUG +#if defined DEBUGWRAPPER +# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__) +#else +# define DEBUG(format, ...) +#endif + +const char *program_name = NULL; + +void * xmalloc (size_t num); +char * xstrdup (const char *string); +const char * base_name (const char *name); +char * find_executable(const char *wrapper); +int check_executable(const char *path); +char * strendzap(char *str, const char *pat); +void lt_fatal (const char *message, ...); + +int +main (int argc, char *argv[]) +{ + char **newargz; + int i; + + program_name = (char *) xstrdup (base_name (argv[0])); + DEBUG("(main) argv[0] : %s\n",argv[0]); + DEBUG("(main) program_name : %s\n",program_name); + newargz = XMALLOC(char *, argc+2); +EOF + + cat >> $cwrappersource <<EOF + newargz[0] = (char *) xstrdup("$SHELL"); +EOF + + cat >> $cwrappersource <<"EOF" + newargz[1] = find_executable(argv[0]); + if (newargz[1] == NULL) + lt_fatal("Couldn't find %s", argv[0]); + DEBUG("(main) found exe at : %s\n",newargz[1]); + /* we know the script has the same name, without the .exe */ + /* so make sure newargz[1] doesn't end in .exe */ + strendzap(newargz[1],".exe"); + for (i = 1; i < argc; i++) + newargz[i+1] = xstrdup(argv[i]); + newargz[argc+1] = NULL; + + for (i=0; i<argc+1; i++) + { + DEBUG("(main) newargz[%d] : %s\n",i,newargz[i]); + ; + } + +EOF + + case $host_os in + mingw*) + cat >> $cwrappersource <<EOF + execv("$SHELL",(char const **)newargz); +EOF + ;; + *) + cat >> $cwrappersource <<EOF + execv("$SHELL",newargz); +EOF + ;; + esac + + cat >> $cwrappersource <<"EOF" + return 127; +} + +void * +xmalloc (size_t num) +{ + void * p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL +; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char)name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable(const char * path) +{ + struct stat st; + + DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!"); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) && + ( + /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */ +#if defined (S_IXOTH) + ((st.st_mode & S_IXOTH) == S_IXOTH) || +#endif +#if defined (S_IXGRP) + ((st.st_mode & S_IXGRP) == S_IXGRP) || +#endif + ((st.st_mode & S_IXUSR) == S_IXUSR)) + ) + return 1; + else + return 0; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise */ +char * +find_executable (const char* wrapper) +{ + int has_slash = 0; + const char* p; + const char* p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char* concat_name; + + DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char* path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char* q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR(*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + return NULL; +} + +char * +strendzap(char *str, const char *pat) +{ + size_t len, patlen; + + assert(str != NULL); + assert(pat != NULL); + + len = strlen(str); + patlen = strlen(pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp(str, pat) == 0) + *str = '\0'; + } + return str; +} + +static void +lt_error_core (int exit_status, const char * mode, + const char * message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} +EOF + # we should really use a build-platform specific compiler + # here, but OTOH, the wrappers (shell script and this C one) + # are only useful if you want to execute the "real" binary. + # Since the "real" binary is built for $host, then this + # wrapper might as well be built for $host, too. + $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource + ;; + esac + $rm $output + trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variable: + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $echo >> $output "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $mkdir \"\$progdir\" + else + $rm \"\$progdir/\$file\" + fi" + + $echo >> $output "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $echo \"\$relink_command_output\" >&2 + $rm \"\$progdir/\$file\" + exit $EXIT_FAILURE + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + $echo >> $output "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2*) + $echo >> $output "\ + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $echo >> $output "\ + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit $EXIT_FAILURE + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + $echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit $EXIT_FAILURE + fi +fi\ +" + chmod +x $output + fi + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $addlibs + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + $echo "X$obj" | $Xsed -e 's%^.*/%%' + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "copying selected object files to avoid basename conflicts..." + + if test -z "$gentop"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "$mkdir $gentop" + $run $mkdir "$gentop" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$gentop"; then + exit $exit_status + fi + fi + + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + counter=`expr $counter + 1` + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + $run ln "$obj" "$gentop/$newobj" || + $run cp "$obj" "$gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + + eval cmds=\"$old_archive_cmds\" + + if len=`expr "X$cmds" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + $echo "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + for obj in $save_oldobjs + do + oldobjs="$objlist $obj" + objlist="$objlist $obj" + eval test_cmds=\"$old_archive_cmds\" + if len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + eval cmd=\"$cmd\" + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + + # Only create the output if not a dry run. + if test -z "$run"; then + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + for lib in $dlfiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlfiles="$newdlfiles $libdir/$name" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlprefiles="$newdlprefiles $libdir/$name" + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $rm $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $echo >> $output "\ +relink_command=\"$relink_command\"" + fi + done + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? + ;; + esac + exit $EXIT_SUCCESS + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $echo "X$nonopt" | grep shtool > /dev/null; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) prev=$arg ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test "$#" -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + library_names= + old_library= + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + if test "$inst_prefix_dir" = "$destdir"; then + $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + $echo "$modename: warning: relinking \`$file'" 1>&2 + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + exit $EXIT_FAILURE + fi + fi + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$srcname $destdir/$realname" + $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? + if test -n "$stripme" && test -n "$striplib"; then + $show "$striplib $destdir/$realname" + $run eval "$striplib $destdir/$realname" || exit $? + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + if test "$linkname" != "$realname"; then + $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + cmds=$postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + file=`$echo $file|${SED} 's,.exe$,,'` + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin*|*mingw*) + wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` + ;; + *) + wrapper=$file + ;; + esac + if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then + notinst_deplibs= + relink_command= + + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + # Check the variables that should have been set. + if test -z "$notinst_deplibs"; then + $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 + exit $EXIT_FAILURE + fi + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + relink_command= + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir=`func_mktempdir` + file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` + ;; + esac + ;; + esac + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + if test -n "$stripme" && test -n "$old_striplib"; then + $show "$old_striplib $oldlib" + $run eval "$old_striplib $oldlib" || exit $? + fi + + # Do each command in the postinstall commands. + cmds=$old_postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + cmds=$finish_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = : && exit $EXIT_SUCCESS + + $echo "X----------------------------------------------------------------------" | $Xsed + $echo "Libraries have been installed in:" + for libdir in $libdirs; do + $echo " $libdir" + done + $echo + $echo "If you ever happen to want to link against installed libraries" + $echo "in a given directory, LIBDIR, you must either use libtool, and" + $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + $echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + $echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + $echo " during execution" + fi + if test -n "$runpath_var"; then + $echo " - add LIBDIR to the \`$runpath_var' environment variable" + $echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $echo " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $echo " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + $echo + $echo "See any operating system documentation about shared libraries for" + $echo "more information, such as the ld(1) and ld.so(8) manual pages." + $echo "X----------------------------------------------------------------------" | $Xsed + exit $EXIT_SUCCESS + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit $EXIT_FAILURE + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit $EXIT_FAILURE + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + if test "${save_LC_ALL+set}" = set; then + LC_ALL="$save_LC_ALL"; export LC_ALL + fi + if test "${save_LANG+set}" = set; then + LANG="$save_LANG"; export LANG + fi + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + fi + $echo "$cmd$args" + exit $EXIT_SUCCESS + fi + ;; + + # libtool clean and uninstall mode + clean | uninstall) + modename="$modename: $mode" + rm="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) rm="$rm $arg"; rmforce=yes ;; + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$file"; then + dir=. + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if (test -L "$file") >/dev/null 2>&1 \ + || (test -h "$file") >/dev/null 2>&1 \ + || test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + cmds=$postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + cmds=$old_postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + + # Read the .lo file + . $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" \ + && test "$pic_object" != none; then + rmfiles="$rmfiles $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" \ + && test "$non_pic_object" != none; then + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + file=`$echo $file|${SED} 's,.exe$,,'` + noexename=`$echo $name|${SED} 's,.exe$,,'` + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + relink_command= + . $dir/$noexename + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + $show "$rm $rmfiles" + $run $rm $rmfiles || exit_status=1 + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + $show "rmdir $dir" + $run rmdir $dir >/dev/null 2>&1 + fi + done + + exit $exit_status + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test -z "$exec_cmd"; then + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + fi +fi # test -z "$show_help" + +if test -n "$exec_cmd"; then + eval exec $exec_cmd + exit $EXIT_FAILURE +fi + +# We need to display help for each of the modes. +case $mode in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + + --config show all configuration variables + --debug enable verbose shell tracing +-n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + --version print version information + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE. + +Report bugs to <bug-libtool@gnu.org>." + exit $EXIT_SUCCESS + ;; + +clean) + $echo \ +"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -static always build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + +uninstall) + $echo \ +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; +esac + +$echo +$echo "Try \`$modename --help' for more information about other modes." + +exit $? + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +disable_libs=shared +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +disable_libs=static +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: Added: freeswitch/trunk/libs/libetpan/src/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +Makefile +*.la Added: freeswitch/trunk/libs/libetpan/src/Makefile.in ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/Makefile.in Wed Dec 20 15:28:56 2006 @@ -0,0 +1,68 @@ +top_builddir = .. +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libdir = @libdir@ +includedir = @includedir@ +mandir = @mandir@ +bindir = @bindir@ +SHELL = /bin/sh +RM = rm -fr +INSTALL = @INSTALL@ +LIBTOOL = @LIBTOOL@ +@SET_MAKE@ + +TARGET = libetpan@LIBSUFFIX@.la + +VERSINFO = @API_VERSION@ +CC = @CC@ +LDFLAGS = @LDFLAGS@ @LIBS@ @SSLLIBS@ @LIBICONV@ @DBLIB@ @GNUTLSLIB@ @SASLLIBS@ + +SUBLIBS = data-types/libdata-types.la \ + low-level/liblow-level.la \ + driver/libdriver.la \ + main/libmain.la \ + engine/libengine.la + + +SUBDIRS = data-types \ + low-level \ + driver \ + main \ + engine + + +all: $(TARGET) + +$(TARGET): Makefile $(SUBLIBS) + $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ $(SUBLIBS) \ + -rpath $(libdir) -version-info $(VERSINFO) + +$(SUBLIBS): all-recursive + +install: all install-dirs install-recursive + $(LIBTOOL) --mode=install $(INSTALL) -m 644 $(TARGET) $(DESTDIR)$(libdir) + +install-dirs: + $(INSTALL) -d -m 755 $(DESTDIR)$(libdir) + +clean: clean-recursive + $(RM) -fr $(TARGET) .libs + +prepare: prepare-recursive + +all-recursive install-recursive clean-recursive \ + distclean-recursive prepare-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + target=`echo $@ | sed s/-recursive//`; \ + echo "Making $$target in $$subdir"; \ + (cd $$subdir && $(MAKE) $$target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" + +Makefile: Makefile.in ../config.status + cd ${top_builddir} && CONFIG_FILES=src/Makefile CONFIG_HEADERS= ./config.status + +distclean: clean + rm -rf Makefile + Added: freeswitch/trunk/libs/libetpan/src/bsd/getopt.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/bsd/getopt.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,149 @@ +/* $NetBSD: getopt.c,v 1.26 2003/08/07 16:43:40 agc Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + Modified by Sebastien Marinier for windows OS +*/ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95"; +#endif /* LIBC_SCCS and not lint */ + +#ifdef _MSC_VER +# define _getprogname() nargv[0] +#else +# include <sys/cdefs.h> +__FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/stdlib/getopt.c,v 1.7 2004/03/06 17:05:45 ache Exp $"); + +#include "namespace.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "un-namespace.h" + +#include "libc_private.h" +#endif + + + +int opterr = 1, /* if error message should be printed */ + optind = 1, /* index into parent argv vector */ + optopt, /* character checked for validity */ + optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ + +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" + +/* + * getopt -- + * Parse argc/argv argument vector. + */ +int +getopt(nargc, nargv, ostr) + int nargc; + char * const nargv[]; + const char *ostr; +{ + static char *place = EMSG; /* option letter processing */ + char *oli; /* option letter list index */ + + if (optreset || *place == 0) { /* update scanning pointer */ + optreset = 0; + place = nargv[optind]; + if (optind >= nargc || *place++ != '-') { + /* Argument is absent or is not an option */ + place = EMSG; + return (-1); + } + optopt = *place++; + if (optopt == '-' && *place == 0) { + /* "--" => end of options */ + ++optind; + place = EMSG; + return (-1); + } + if (optopt == 0) { + /* Solitary '-', treat as a '-' option + if the program (eg su) is looking for it. */ + place = EMSG; + if (strchr(ostr, '-') == NULL) + return (-1); + optopt = '-'; + } + } else + optopt = *place++; + + /* See if option letter is one the caller wanted... */ + if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) { + if (*place == 0) + ++optind; + if (opterr && *ostr != ':') + (void)fprintf(stderr, + "%s: illegal option -- %c\n", _getprogname(), + optopt); + return (BADCH); + } + + /* Does this option need an argument? */ + if (oli[1] != ':') { + /* don't need argument */ + optarg = NULL; + if (*place == 0) + ++optind; + } else { + /* Option-argument is either the rest of this argument or the + entire next argument. */ + if (*place) + optarg = place; + else if (nargc > ++optind) + optarg = nargv[optind]; + else { + /* option-argument absent */ + place = EMSG; + if (*ostr == ':') + return (BADARG); + if (opterr) + (void)fprintf(stderr, + "%s: option requires an argument -- %c\n", + _getprogname(), optopt); + return (BADCH); + } + place = EMSG; + ++optind; + } + return (optopt); /* return option letter */ +} Added: freeswitch/trunk/libs/libetpan/src/bsd/getopt.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/bsd/getopt.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,93 @@ +/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ +/* $FreeBSD: /repoman/r/ncvs/src/include/getopt.h,v 1.6 2004/02/24 08:09:20 ache Exp $ */ + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + Modified by Sebastien Marinier for windows OS +*/ + +#ifndef _GETOPT_H_ +#define _GETOPT_H_ + +#ifdef _MSC_VER +# define __BEGIN_DECLS +# define __END_DECLS +#else +# include <sys/cdefs.h> +#endif + +/* + * GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension. + * getopt() is declared here too for GNU programs. + */ +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +struct option { + /* name of long option */ + const char *name; + /* + * one of no_argument, required_argument, and optional_argument: + * whether option takes an argument + */ + int has_arg; + /* if not NULL, set *flag to val when option found */ + int *flag; + /* if flag not NULL, value to set *flag to; else return value */ + int val; +}; + +__BEGIN_DECLS +int getopt_long(int, char * const *, const char *, + const struct option *, int *); +int getopt_long_only(int, char * const *, const char *, + const struct option *, int *); +#ifndef _GETOPT_DECLARED +#define _GETOPT_DECLARED +int getopt(int, char * const [], const char *); + +extern char *optarg; /* getopt(3) external variables */ +extern int optind, opterr, optopt; +#endif +#ifndef _OPTRESET_DECLARED +#define _OPTRESET_DECLARED +extern int optreset; /* getopt(3) external variable */ +#endif +__END_DECLS + +#endif /* !_GETOPT_H_ */ Added: freeswitch/trunk/libs/libetpan/src/bsd/getopt_long.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/bsd/getopt_long.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,651 @@ +/* $OpenBSD: getopt_long.c,v 1.17 2004/06/03 18:46:52 millert Exp $ */ +/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ + +/* + * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + Modified by Sebastien Marinier for windows OS +*/ + +#if 0 +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = "$OpenBSD: getopt_long.c,v 1.16 2004/02/04 18:17:25 millert Exp $"; +#endif /* LIBC_SCCS and not lint */ +#endif +#ifdef _MSC_VER +#include "getopt.h" + static void warnx() { + } +#else +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/stdlib/getopt_long.c,v 1.12 2004/07/06 13:58:45 ache Exp $"); + +#include <err.h> +#include <errno.h> +#include <getopt.h> +#endif +#include <stdlib.h> +#include <string.h> + +#define GNU_COMPATIBLE /* Be more compatible, configure's use us! */ + +#ifndef GNU_COMPATIBLE +#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ +#endif + +#ifdef REPLACE_GETOPT +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ +#endif + +#define PRINT_ERROR ((opterr) && (*options != ':')) + +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#define EMSG "" + +#ifdef GNU_COMPATIBLE +#define NO_PREFIX (-1) +#define D_PREFIX 0 +#define DD_PREFIX 1 +#define W_PREFIX 2 +#endif + +static int getopt_internal(int, char * const *, const char *, + const struct option *, int *, int); +static int parse_long_options(char * const *, const char *, + const struct option *, int *, int, int); +static int gcd(int, int); +static void permute_args(int, int, int, char * const *); + +static char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* Error messages */ +static const char recargchar[] = "option requires an argument -- %c"; +static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */ +#ifdef GNU_COMPATIBLE +static int dash_prefix = NO_PREFIX; +static const char gnuoptchar[] = "invalid option -- %c"; + +static const char recargstring[] = "option `%s%s' requires an argument"; +static const char ambig[] = "option `%s%.*s' is ambiguous"; +static const char noarg[] = "option `%s%.*s' doesn't allow an argument"; +static const char illoptstring[] = "unrecognized option `%s%s'"; +#else +static const char recargstring[] = "option requires an argument -- %s"; +static const char ambig[] = "ambiguous option -- %.*s"; +static const char noarg[] = "option doesn't take an argument -- %.*s"; +static const char illoptstring[] = "unknown option -- %s"; +#endif + +/* + * Compute the greatest common divisor of a and b. + */ +static int +gcd(int a, int b) +{ + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return (b); +} + +/* + * Exchange the block from nonopt_start to nonopt_end with the block + * from nonopt_end to opt_end (keeping the same order of arguments + * in each block). + */ +static void +permute_args(int panonopt_start, int panonopt_end, int opt_end, + char * const *nargv) +{ + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **) nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } +} + +/* + * parse_long_options -- + * Parse long options in argc/argv argument vector. + * Returns -1 if short_too is set and the option does not match long_options. + */ +static int +parse_long_options(char * const *nargv, const char *options, + const struct option *long_options, int *idx, int short_too, int flags) +{ + char *current_argv, *has_equal; +#ifdef GNU_COMPATIBLE + char *current_dash; +#endif + size_t current_argv_len; + int i, match, exact_match, second_partial_match; + + current_argv = place; +#ifdef GNU_COMPATIBLE + switch (dash_prefix) { + case D_PREFIX: + current_dash = "-"; + break; + case DD_PREFIX: + current_dash = "--"; + break; + case W_PREFIX: + current_dash = "-W "; + break; + default: + current_dash = ""; + break; + } +#endif + match = -1; + exact_match = 0; + second_partial_match = 0; + + optind++; + + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + exact_match = 1; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* first partial match */ + match = i; + else if ((flags & FLAG_LONGONLY) || + long_options[i].has_arg != + long_options[match].has_arg || + long_options[i].flag != long_options[match].flag || + long_options[i].val != long_options[match].val) + second_partial_match = 1; + } + if (!exact_match && second_partial_match) { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, +#ifdef GNU_COMPATIBLE + current_dash, +#endif + (int)current_argv_len, + current_argv); + optopt = 0; + return (BADCH); + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, +#ifdef GNU_COMPATIBLE + current_dash, +#endif + (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; +#ifdef GNU_COMPATIBLE + return (BADCH); +#else + return (BADARG); +#endif + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, +#ifdef GNU_COMPATIBLE + current_dash, +#endif + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return (BADARG); + } + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, +#ifdef GNU_COMPATIBLE + current_dash, +#endif + current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); +} + +/* + * getopt_internal -- + * Parse argc/argv argument vector. Called by user level routines. + */ +static int +getopt_internal(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx, int flags) +{ + char *oli; /* option letter list index */ + int optchar, short_too; + int posixly_correct; + + if (options == NULL) + return (-1); + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + */ + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); +#ifdef GNU_COMPATIBLE + if (*options == '-') + flags |= FLAG_ALLARGS; + else if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; +#else + if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + else if (*options == '-') + flags |= FLAG_ALLARGS; +#endif + if (*options == '+' || *options == '-') + options++; + + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; + + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || +#ifdef GNU_COMPATIBLE + place[1] == '\0') { +#else + (place[1] == '\0' && strchr(options, '-') == NULL)) { +#endif + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { + /* + * If no permutation wanted, stop parsing + * at first non-option. + */ + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } + + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; +#ifdef GNU_COMPATIBLE + dash_prefix = D_PREFIX; +#endif + if (*place == '-') { + place++; /* --foo long option */ +#ifdef GNU_COMPATIBLE + dash_prefix = DD_PREFIX; +#endif + } else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, + idx, short_too, flags); + if (optchar != -1) { + place = EMSG; + return (optchar); + } + } + + if ((optchar = (int)*place++) == (int)':' || + (optchar == (int)'-' && *place != '\0') || + (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; +#ifdef GNU_COMPATIBLE + if (PRINT_ERROR) + warnx(posixly_correct ? illoptchar : gnuoptchar, + optchar); +#else + if (PRINT_ERROR) + warnx(illoptchar, optchar); +#endif + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else /* white space */ + place = nargv[optind]; +#ifdef GNU_COMPATIBLE + dash_prefix = W_PREFIX; +#endif + optchar = parse_long_options(nargv, options, long_options, + idx, 0, flags); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + /* XXX: disable test for :: if PC? (GNU doesn't) */ + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else + optarg = nargv[optind]; + } else if (!(flags & FLAG_PERMUTE)) { + /* + * If permutation is disabled, we can accept an + * optional arg separated by whitespace so long + * as it does not start with a dash (-). + */ + if (optind + 1 < nargc && *nargv[optind + 1] != '-') + optarg = nargv[++optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); +} + +#ifdef REPLACE_GETOPT +/* + * getopt -- + * Parse argc/argv argument vector. + * + * [eventually this will replace the BSD getopt] + */ +int +getopt(int nargc, char * const *nargv, const char *options) +{ + + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); +} +#endif /* REPLACE_GETOPT */ + +/* + * getopt_long -- + * Parse argc/argv argument vector. + */ +int +getopt_long(nargc, nargv, options, long_options, idx) + int nargc; + char * const *nargv; + const char *options; + const struct option *long_options; + int *idx; +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE)); +} + +/* + * getopt_long_only -- + * Parse argc/argv argument vector. + */ +int +getopt_long_only(nargc, nargv, options, long_options, idx) + int nargc; + char * const *nargv; + const char *options; + const struct option *long_options; + int *idx; +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE|FLAG_LONGONLY)); +} Added: freeswitch/trunk/libs/libetpan/src/data-types/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/data-types/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,17 @@ +top_builddir = ../.. + +TARGET = libdata-types +HEADERS = mmapstring.h mailstream.h mailstream_helper.h mail.h \ + mailstream_low.h \ + mailstream_socket.h mailstream_ssl.h \ + mailstream_types.h \ + carray.h clist.h chash.h cinthash.h \ + charconv.h mailsem.h maillock.h +SOURCES = connect.c md5.c mmapstring.c \ + mailstream_helper.c mailstream_low.c \ + mailstream.c mailstream_socket.c mailstream_ssl.c \ + mapping.c cinthash.c carray.c clist.c chash.c \ + charconv.c maillock.c base64.c \ + mail_cache_db.c mailsem.c mailsasl.c + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/data-types/base64.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/base64.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,145 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - Juergen Graf + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: base64.c,v 1.3 2005/06/01 12:21:57 smarinier Exp $ + */ + +#include "base64.h" + +#include <stdlib.h> + +#define OUTPUT_SIZE 513 +#define CHAR64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) + +static char index_64[128] = { + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 +}; + +static char basis_64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +LIBETPAN_EXPORT +char * encode_base64(const char * in, int len) +{ + char * output, * tmp; + unsigned char oval; + int out_len; + + out_len = ((len + 2) / 3 * 4) + 1; + + if ((len > 0) && (in == NULL)) + return NULL; + + output = malloc(out_len); + if (!output) + return NULL; + + tmp = output; + while (len >= 3) { + *tmp++ = basis_64[in[0] >> 2]; + *tmp++ = basis_64[((in[0] << 4) & 0x30) | (in[1] >> 4)]; + *tmp++ = basis_64[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; + *tmp++ = basis_64[in[2] & 0x3f]; + in += 3; + len -= 3; + } + if (len > 0) { + *tmp++ = basis_64[in[0] >> 2]; + oval = (in[0] << 4) & 0x30; + if (len > 1) oval |= in[1] >> 4; + *tmp++ = basis_64[oval]; + *tmp++ = (len < 2) ? '=' : basis_64[(in[1] << 2) & 0x3c]; + *tmp++ = '='; + } + + *tmp = '\0'; + + return output; +} + +LIBETPAN_EXPORT +char * decode_base64(const char * in, int len) +{ + char * output, * out; + int i, c1, c2, c3, c4, out_len; + + out_len = 0; + + output = malloc(OUTPUT_SIZE); + if (output == NULL) + return NULL; + out = output; + + if (in[0] == '+' && in[1] == ' ') + in += 2; + + for (i = 0; i < (len / 4); i++) { + c1 = in[0]; + c2 = in[1]; + c3 = in[2]; + c4 = in[3]; + if (CHAR64(c1) == -1 || CHAR64(c2) == -1 || + (c3 != '=' && CHAR64(c3) == -1) || + (c4 != '=' && CHAR64(c4) == -1)) + return NULL; + + in += 4; + *output++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4); + if (++out_len >= OUTPUT_SIZE) + return NULL; + + if (c3 != '=') { + *output++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2); + if (++out_len >= OUTPUT_SIZE) + return NULL; + + if (c4 != '=') { + *output++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4); + if (++out_len >= OUTPUT_SIZE) + return NULL; + } + } + } + + *output = 0; + + return out; +} + + Added: freeswitch/trunk/libs/libetpan/src/data-types/base64.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/base64.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,65 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - Juergen Graf + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: base64.h,v 1.3 2005/06/01 12:21:57 smarinier Exp $ + */ + +#ifndef BASE64_H +#define BASE64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LIBETPAN_CONFIG_H +# include "libetpan-config.h" +#endif + +/** + * creates (malloc) a new base64 encoded string from a standard 8bit string + * don't forget to free it when time comes ;) + */ +LIBETPAN_EXPORT +char * encode_base64(const char * in, int len); + +/** + * creates (malloc) a new standard 8bit string from an base64 encoded string + * don't forget to free it when time comes ;) + */ +LIBETPAN_EXPORT +char * decode_base64(const char * in, int len); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/carray.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/carray.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,162 @@ +/* + * libEtPan! -- a mail stuff library + * + * carray - Implements simple dynamic pointer arrays + * + * Copyright (c) 1999-2005, Ga�l Roualland <gael.roualland@iname.com> + * interface changes - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: carray.c,v 1.10 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include "carray.h" + +#define MIN_ARRAY_SIZE 4 + +LIBETPAN_EXPORT +carray * carray_new(unsigned int initsize) { + carray * array; + + array = (carray *) malloc(sizeof(carray)); + if (!array) return NULL; + + if (initsize < MIN_ARRAY_SIZE) + initsize = MIN_ARRAY_SIZE; + + array->len = 0; + array->max = initsize; + array->array = (void **) malloc(sizeof(void *) * initsize); + if (!array->array) { + free(array); + return NULL; + } + return array; +} + +LIBETPAN_EXPORT +int carray_add(carray * array, void * data, unsigned int * index) { + int r; + + r = carray_set_size(array, array->len + 1); + if (r < 0) + return r; + + array->array[array->len - 1] = data; + if (index != NULL) + * index = array->len - 1; + + return 0; +} + +LIBETPAN_EXPORT +int carray_set_size(carray * array, unsigned int new_size) +{ + if (new_size > array->max) { + unsigned int n = array->max * 2; + void * new; + + while (n <= new_size) + n *= 2; + + new = (void **) realloc(array->array, sizeof(void *) * n); + if (!new) + return -1; + array->array = new; + array->max = n; + } + array->len = new_size; + + return 0; +} + +LIBETPAN_EXPORT +int carray_delete_fast(carray * array, unsigned int indx) { + if (indx >= array->len) + return -1; + + array->array[indx] = NULL; + + return 0; +} + +LIBETPAN_EXPORT +int carray_delete(carray * array, unsigned int indx) { + if (indx >= array->len) + return -1; + + if (indx != --array->len) + array->array[indx] = array->array[array->len]; + return 0; +} + +LIBETPAN_EXPORT +int carray_delete_slow(carray * array, unsigned int indx) { + if (indx >= array->len) + return -1; + + if (indx != --array->len) + memmove(array->array + indx, array->array + indx + 1, + (array->len - indx) * sizeof(void *)); + return 0; +} + +#ifdef NO_MACROS +LIBETPAN_EXPORT +void ** carray_data(carray * array) { + return array->array; +} + +LIBETPAN_EXPORT +unsigned int carray_count(carray * array) { + return array->len; +} + +LIBETPAN_EXPORT +void * carray_get(carray * array, unsigned int indx) { + return array->array[indx]; +} + +LIBETPAN_EXPORT +void carray_set(carray * array, unsigned int indx, void * value) { + array->array[indx] = value; +} +#endif + +LIBETPAN_EXPORT +void carray_free(carray * array) { + free(array->array); + free(array); +} Added: freeswitch/trunk/libs/libetpan/src/data-types/carray.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/carray.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,138 @@ +/* + * libEtPan! -- a mail stuff library + * + * carray - Implements simple dynamic pointer arrays + * + * Copyright (c) 1999-2005, Ga�l Roualland <gael.roualland@iname.com> + * interface changes - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: carray.h,v 1.16 2006/03/22 08:10:47 hoa Exp $ + */ + +#ifndef CARRAY_H +#define CARRAY_H + +#ifndef LIBETPAN_CONFIG_H +# include <libetpan/libetpan-config.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct carray_s { + void ** array; + unsigned int len; + unsigned int max; +}; + +typedef struct carray_s carray; + +/* Creates a new array of pointers, with initsize preallocated cells */ +LIBETPAN_EXPORT +carray * carray_new(unsigned int initsize); + +/* Adds the pointer to data in the array. + Returns the index of the pointer in the array or -1 on error */ +LIBETPAN_EXPORT +int carray_add(carray * array, void * data, unsigned int * index); + +LIBETPAN_EXPORT +int carray_set_size(carray * array, unsigned int new_size); + +/* Removes the cell at this index position. Returns TRUE on success. + Order of elements in the array IS changed. */ +LIBETPAN_EXPORT +int carray_delete(carray * array, unsigned int indx); + +/* Removes the cell at this index position. Returns TRUE on success. + Order of elements in the array IS not changed. */ +LIBETPAN_EXPORT +int carray_delete_slow(carray * array, unsigned int indx); + +/* remove without decreasing the size of the array */ +LIBETPAN_EXPORT +int carray_delete_fast(carray * array, unsigned int indx); + +/* Some of the following routines can be implemented as macros to + be faster. If you don't want it, define NO_MACROS */ +#ifdef NO_MACROS + +/* Returns the array itself */ +LIBETPAN_EXPORT +void ** carray_data(carray *); + +/* Returns the number of elements in the array */ +LIBETPAN_EXPORT +unsigned int carray_count(carray *); + +/* Returns the contents of one cell */ +LIBETPAN_EXPORT +void * carray_get(carray * array, unsigned int indx); + +/* Sets the contents of one cell */ +LIBETPAN_EXPORT +void carray_set(carray * array, unsigned int indx, void * value); + +#else + +#if 0 +#define carray_data(a) (a->array) +#define carray_count(a) (a->len) +#define carray_get(a, indx) (a->array[indx]) +#define carray_set(a, indx, v) do { a->array[indx]=v; } while(0) +#endif + +static inline void ** carray_data(carray * array) { + return array->array; +} + +static inline unsigned int carray_count(carray * array) { + return array->len; +} + +static inline void * carray_get(carray * array, unsigned int indx) { + return array->array[indx]; +} + +static inline void carray_set(carray * array, + unsigned int indx, void * value) { + array->array[indx] = value; +} +#endif + +LIBETPAN_EXPORT +void carray_free(carray * array); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/charconv.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/charconv.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,316 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: charconv.c,v 1.22 2006/07/03 16:36:08 skunk Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "charconv.h" + +#ifdef HAVE_ICONV +#include <iconv.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> + +#include "mmapstring.h" + +int (*extended_charconv)(const char * tocode, const char * fromcode, const char * str, size_t length, + char * result, size_t* result_len) = NULL; + +#ifdef HAVE_ICONV +static size_t mail_iconv (iconv_t cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft, + char **inrepls, char *outrepl) +{ + size_t ret = 0, ret1; + /* XXX - force const to mutable */ + char *ib = (char *) *inbuf; + size_t ibl = *inbytesleft; + char *ob = *outbuf; + size_t obl = *outbytesleft; + + for (;;) + { +#ifdef HAVE_ICONV_PROTO_CONST + ret1 = iconv (cd, (const char **) &ib, &ibl, &ob, &obl); +#else + ret1 = iconv (cd, &ib, &ibl, &ob, &obl); +#endif + if (ret1 != (size_t)-1) + ret += ret1; + if (ibl && obl && errno == EILSEQ) + { + if (inrepls) + { + /* Try replacing the input */ + char **t; + for (t = inrepls; *t; t++) + { + char *ib1 = *t; + size_t ibl1 = strlen (*t); + char *ob1 = ob; + size_t obl1 = obl; +#ifdef HAVE_ICONV_PROTO_CONST + iconv (cd, (const char **) &ib1, &ibl1, &ob1, &obl1); +#else + iconv (cd, &ib1, &ibl1, &ob1, &obl1); +#endif + if (!ibl1) + { + ++ib, --ibl; + ob = ob1, obl = obl1; + ++ret; + break; + } + } + if (*t) + continue; + } + if (outrepl) + { + /* Try replacing the output */ + size_t n = strlen (outrepl); + if (n <= obl) + { + memcpy (ob, outrepl, n); + ++ib, --ibl; + ob += n, obl -= n; + ++ret; + continue; + } + } + } + *inbuf = ib, *inbytesleft = ibl; + *outbuf = ob, *outbytesleft = obl; + return ret; + } +} +#endif + +LIBETPAN_EXPORT +int charconv(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result) +{ +#ifdef HAVE_ICONV + iconv_t conv; + size_t r; + char * pout; + size_t out_size; + size_t old_out_size; + size_t count; +#endif + char * out; + int res; + + if (extended_charconv != NULL) { + size_t result_length; + result_length = length * 6; + *result = malloc( length * 6 + 1); + if (*result == NULL) { + res = MAIL_CHARCONV_ERROR_MEMORY; + } else { + res = (*extended_charconv)( tocode, fromcode, str, length, *result, &result_length); + if (res != MAIL_CHARCONV_NO_ERROR) { + free( *result); + } else { + out = realloc( *result, result_length + 1); + if (out != NULL) *result = out; + /* also a cstring, just in case */ + (*result)[result_length] = '\0'; + } + } + if (res != MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET) + return res; + /* else, let's try with iconv, if available */ + } + +#ifndef HAVE_ICONV + return MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; +#else + + conv = iconv_open(tocode, fromcode); + if (conv == (iconv_t) -1) { + res = MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; + goto err; + } + + out_size = 6 * length; /* UTF-8 can be encoded up to 6 bytes */ + + out = malloc(out_size + 1); + if (out == NULL) { + res = MAIL_CHARCONV_ERROR_MEMORY; + goto close_iconv; + } + + pout = out; + old_out_size = out_size; + + r = mail_iconv(conv, &str, &length, &pout, &out_size, NULL, "?"); + + if (r == (size_t) -1) { + res = MAIL_CHARCONV_ERROR_CONV; + goto free; + } + + iconv_close(conv); + + * pout = '\0'; + count = old_out_size - out_size; + pout = realloc(out, count + 1); + if (pout != NULL) + out = pout; + + * result = out; + + return MAIL_CHARCONV_NO_ERROR; + + free: + free(out); + close_iconv: + iconv_close(conv); + err: + return res; +#endif +} + +LIBETPAN_EXPORT +int charconv_buffer(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result, size_t * result_len) +{ +#ifdef HAVE_ICONV + iconv_t conv; + size_t iconv_r; + int r; + char * out; + char * pout; + size_t out_size; + size_t old_out_size; + size_t count; +#endif + int res; + MMAPString * mmapstr; + + if (extended_charconv != NULL) { + size_t result_length; + result_length = length * 6; + mmapstr = mmap_string_sized_new( result_length + 1); + *result_len = 0; + if (mmapstr == NULL) { + res = MAIL_CHARCONV_ERROR_MEMORY; + } else { + res = (*extended_charconv)( tocode, fromcode, str, length, mmapstr->str, &result_length); + if (res != MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET) { + if (res == MAIL_CHARCONV_NO_ERROR) { + *result = mmapstr->str; + res = mmap_string_ref(mmapstr); + if (res < 0) { + res = MAIL_CHARCONV_ERROR_MEMORY; + mmap_string_free(mmapstr); + } else { + mmap_string_set_size( mmapstr, result_length); /* can't fail */ + *result_len = result_length; + } + } + free( *result); + } + return res; + } + /* else, let's try with iconv, if available */ + } + +#ifndef HAVE_ICONV + return MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; +#else + + conv = iconv_open(tocode, fromcode); + if (conv == (iconv_t) -1) { + res = MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET; + goto err; + } + + out_size = 6 * length; /* UTF-8 can be encoded up to 6 bytes */ + + mmapstr = mmap_string_sized_new(out_size + 1); + if (mmapstr == NULL) { + res = MAIL_CHARCONV_ERROR_MEMORY; + goto err; + } + + out = mmapstr->str; + + pout = out; + old_out_size = out_size; + + iconv_r = mail_iconv(conv, &str, &length, &pout, &out_size, NULL, "?"); + + if (iconv_r == (size_t) -1) { + res = MAIL_CHARCONV_ERROR_CONV; + goto free; + } + + iconv_close(conv); + + * pout = '\0'; + + count = old_out_size - out_size; + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_CHARCONV_ERROR_MEMORY; + goto free; + } + + * result = out; + * result_len = count; + + return MAIL_CHARCONV_NO_ERROR; + + free: + mmap_string_free(mmapstr); + err: + return res; +#endif +} + +LIBETPAN_EXPORT +void charconv_buffer_free(char * str) +{ + mmap_string_unref(str); +} Added: freeswitch/trunk/libs/libetpan/src/data-types/charconv.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/charconv.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,84 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: charconv.h,v 1.13 2006/06/16 09:25:23 smarinier Exp $ + */ + +#ifndef CHARCONV_H + +#define CHARCONV_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> + +#ifndef LIBETPAN_CONFIG_H +# include <libetpan/libetpan-config.h> +#endif + +enum { + MAIL_CHARCONV_NO_ERROR = 0, + MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET, + MAIL_CHARCONV_ERROR_MEMORY, + MAIL_CHARCONV_ERROR_CONV +}; + +/** +* define your own conversion. +* - result is big enough to contain your converted string +* - result_len contain the maximum size available (out value must contain the final converted size) +* - your conversion return an error code based on upper enum values +*/ +LIBETPAN_EXPORT +extern int (*extended_charconv)(const char * tocode, const char * fromcode, const char * str, size_t length, + char * result, size_t* result_len); + +LIBETPAN_EXPORT +int charconv(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result); + +LIBETPAN_EXPORT +int charconv_buffer(const char * tocode, const char * fromcode, + const char * str, size_t length, + char ** result, size_t * result_len); + +LIBETPAN_EXPORT +void charconv_buffer_free(char * str); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/chash.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/chash.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,414 @@ +/* + * libEtPan! -- a mail stuff library + * + * chash - Implements generic hash tables. + * + * Copyright (c) 1999-2005, Ga�l Roualland <gael.roualland@iname.com> + * interface changes - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: chash.c,v 1.16 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <string.h> + +#include "chash.h" + +/* This defines the maximum (average) number of entries per bucket. + The hash is resized everytime inserting an entry makes the + average go over that value. */ +#define CHASH_MAXDEPTH 3 + +static inline unsigned int chash_func(const char * key, unsigned int len) { +#if 0 + register unsigned int c = 0, t; + register const char * k = key; + + while (len--) { + c += (c << 4) + *k++; + if ((t = c & 0xF0000000)) { + c ^= t >> 24; + c ^= t; + } + } + return c; +#endif + register unsigned int c = 5381; + register const char * k = key; + + while (len--) { + c = ((c << 5) + c) + *k++; + } + + return c; +} + +static inline char * chash_dup(const void * data, unsigned int len) +{ + void * r; + + r = (char *) malloc(len); + if (!r) + return NULL; + memcpy(r, data, len); + return r; +} + +LIBETPAN_EXPORT +chash * chash_new(unsigned int size, int flags) +{ + chash * h; + + h = (chash *) malloc(sizeof(chash)); + if (h == NULL) + return NULL; + + if (size < CHASH_DEFAULTSIZE) + size = CHASH_DEFAULTSIZE; + + h->count = 0; + h->cells = (struct chashcell **) calloc(size, sizeof(struct chashcell *)); + if (h->cells == NULL) { + free(h); + return NULL; + } + h->size = size; + h->copykey = flags & CHASH_COPYKEY; + h->copyvalue = flags & CHASH_COPYVALUE; + + return h; +} + +LIBETPAN_EXPORT +int chash_get(chash * hash, + chashdatum * key, chashdatum * result) +{ + unsigned int func; + chashiter * iter; + + func = chash_func(key->data, key->len); + + /* look for the key in existing cells */ + iter = hash->cells[func % hash->size]; + while (iter) { + if (iter->key.len == key->len && iter->func == func + && !memcmp(iter->key.data, key->data, key->len)) { + * result = iter->value; /* found */ + + return 0; + } + iter = iter->next; + } + + return -1; +} + +LIBETPAN_EXPORT +int chash_set(chash * hash, + chashdatum * key, + chashdatum * value, + chashdatum * oldvalue) +{ + unsigned int func, indx; + chashiter * iter, * cell; + int r; + + if (hash->count > hash->size * CHASH_MAXDEPTH) { + r = chash_resize(hash, (hash->count / CHASH_MAXDEPTH) * 2 + 1); + if (r < 0) + goto err; + } + + func = chash_func(key->data, key->len); + indx = func % hash->size; + + /* look for the key in existing cells */ + iter = hash->cells[indx]; + while (iter) { + if (iter->key.len == key->len && iter->func == func + && !memcmp(iter->key.data, key->data, key->len)) { + /* found, replacing entry */ + if (hash->copyvalue) { + char * data; + + data = chash_dup(value->data, value->len); + if (data == NULL) + goto err; + + free(iter->value.data); + iter->value.data = data; + iter->value.len = value->len; + } else { + if (oldvalue != NULL) { + oldvalue->data = iter->value.data; + oldvalue->len = iter->value.len; + } + iter->value.data = value->data; + iter->value.len = value->len; + } + if (!hash->copykey) + iter->key.data = key->data; + + if (oldvalue != NULL) { + oldvalue->data = value->data; + oldvalue->len = value->len; + } + + return 0; + } + iter = iter->next; + } + + if (oldvalue != NULL) { + oldvalue->data = NULL; + oldvalue->len = 0; + } + + /* not found, adding entry */ + cell = (struct chashcell *) malloc(sizeof(struct chashcell)); + if (cell == NULL) + goto err; + + if (hash->copykey) { + cell->key.data = chash_dup(key->data, key->len); + if (cell->key.data == NULL) + goto free; + } + else + cell->key.data = key->data; + + cell->key.len = key->len; + if (hash->copyvalue) { + cell->value.data = chash_dup(value->data, value->len); + if (cell->value.data == NULL) + goto free_key_data; + } + else + cell->value.data = value->data; + + cell->value.len = value->len; + cell->func = func; + cell->next = hash->cells[indx]; + hash->cells[indx] = cell; + hash->count++; + + return 0; + + free_key_data: + if (hash->copykey) + free(cell->key.data); + free: + free(cell); + err: + return -1; +} + +LIBETPAN_EXPORT +int chash_delete(chash * hash, chashdatum * key, chashdatum * oldvalue) +{ + /* chashdatum result = { NULL, TRUE }; */ + unsigned int func, indx; + chashiter * iter, * old; + + /* + if (!keylen) + keylen = strlen(key) + 1; + */ + + func = chash_func(key->data, key->len); + indx = func % hash->size; + + /* look for the key in existing cells */ + old = NULL; + iter = hash->cells[indx]; + while (iter) { + if (iter->key.len == key->len && iter->func == func + && !memcmp(iter->key.data, key->data, key->len)) { + /* found, deleting */ + if (old) + old->next = iter->next; + else + hash->cells[indx] = iter->next; + if (hash->copykey) + free(iter->key.data); + if (hash->copyvalue) + free(iter->value.data); + else { + if (oldvalue != NULL) { + oldvalue->data = iter->value.data; + oldvalue->len = iter->value.len; + } + } + free(iter); + hash->count--; + return 0; + } + old = iter; + iter = iter->next; + } + + return -1; /* not found */ +} + +LIBETPAN_EXPORT +void chash_free(chash * hash) { + unsigned int indx; + chashiter * iter, * next; + + /* browse the hash table */ + for(indx = 0; indx < hash->size; indx++) { + iter = hash->cells[indx]; + while (iter) { + next = iter->next; + if (hash->copykey) + free(iter->key.data); + if (hash->copyvalue) + free(iter->value.data); + free(iter); + iter = next; + } + } + free(hash->cells); + free(hash); +} + +LIBETPAN_EXPORT +void chash_clear(chash * hash) { + unsigned int indx; + chashiter * iter, * next; + + /* browse the hash table */ + for(indx = 0; indx < hash->size; indx++) { + iter = hash->cells[indx]; + while (iter) { + next = iter->next; + if (hash->copykey) + free(iter->key.data); + if (hash->copyvalue) + free(iter->value.data); + free(iter); + iter = next; + } + } + memset(hash->cells, 0, hash->size * sizeof(* hash->cells)); + hash->count = 0; +} + +LIBETPAN_EXPORT +chashiter * chash_begin(chash * hash) { + chashiter * iter; + unsigned int indx = 0; + + iter = hash->cells[0]; + while(!iter) { + indx++; + if (indx >= hash->size) + return NULL; + iter = hash->cells[indx]; + } + return iter; +} + +LIBETPAN_EXPORT +chashiter * chash_next(chash * hash, chashiter * iter) { + unsigned int indx; + + if (!iter) + return NULL; + + indx = iter->func % hash->size; + iter = iter->next; + + while(!iter) { + indx++; + if (indx >= hash->size) + return NULL; + iter = hash->cells[indx]; + } + return iter; +} + +LIBETPAN_EXPORT +int chash_resize(chash * hash, unsigned int size) +{ + struct chashcell ** cells; + unsigned int indx, nindx; + chashiter * iter, * next; + + if (hash->size == size) + return 0; + + cells = (struct chashcell **) calloc(size, sizeof(struct chashcell *)); + if (!cells) + return -1; + + /* browse initial hash and copy items in second hash */ + for(indx = 0; indx < hash->size; indx++) { + iter = hash->cells[indx]; + while (iter) { + next = iter->next; + nindx = iter->func % size; + iter->next = cells[nindx]; + cells[nindx] = iter; + iter = next; + } + } + free(hash->cells); + hash->size = size; + hash->cells = cells; + + return 0; +} + +#ifdef NO_MACROS +LIBETPAN_EXPORT +int chash_count(chash * hash) { + return hash->count; +} + +LIBETPAN_EXPORT +int chash_size(chash * hash) { + return hash->size; +} + +LIBETPAN_EXPORT +void chash_value(chashiter * iter, chashdatum * result) { + * result = iter->value; +} + +LIBETPAN_EXPORT +void chash_key(chashiter * iter, chashdatum * result) { + * result = iter->key; +} +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/chash.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/chash.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,182 @@ +/* + * libEtPan! -- a mail stuff library + * + * chash - Implements generic hash tables. + * + * Copyright (c) 1999-2005, Ga�l Roualland <gael.roualland@iname.com> + * interface changes - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: chash.h,v 1.15 2006/03/22 08:10:47 hoa Exp $ + */ + +#ifndef CHASH_H +#define CHASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LIBETPAN_CONFIG_H +# include <libetpan/libetpan-config.h> +#endif + +typedef struct { + void * data; + unsigned int len; +} chashdatum; + +struct chash { + unsigned int size; + unsigned int count; + int copyvalue; + int copykey; + struct chashcell ** cells; +}; + +typedef struct chash chash; + +struct chashcell { + unsigned int func; + chashdatum key; + chashdatum value; + struct chashcell * next; +}; + +typedef struct chashcell chashiter; + +#define CHASH_COPYNONE 0 +#define CHASH_COPYKEY 1 +#define CHASH_COPYVALUE 2 +#define CHASH_COPYALL (CHASH_COPYKEY | CHASH_COPYVALUE) + +#define CHASH_DEFAULTSIZE 13 + +/* Allocates a new (empty) hash using this initial size and the given flags, + specifying which data should be copied in the hash. + CHASH_COPYNONE : Keys/Values are not copied. + CHASH_COPYKEY : Keys are dupped and freed as needed in the hash. + CHASH_COPYVALUE : Values are dupped and freed as needed in the hash. + CHASH_COPYALL : Both keys and values are dupped in the hash. + */ +LIBETPAN_EXPORT +chash * chash_new(unsigned int size, int flags); + +/* Frees a hash */ +LIBETPAN_EXPORT +void chash_free(chash * hash); + +/* Removes all elements from a hash */ +LIBETPAN_EXPORT +void chash_clear(chash * hash); + +/* Adds an entry in the hash table. + Length can be 0 if key/value are strings. + If an entry already exists for this key, it is replaced, and its value + is returned. Otherwise, the data pointer will be NULL and the length + field be set to TRUE or FALSe to indicate success or failure. */ +LIBETPAN_EXPORT +int chash_set(chash * hash, + chashdatum * key, + chashdatum * value, + chashdatum * oldvalue); + +/* Retrieves the data associated to the key if it is found in the hash table. + The data pointer and the length will be NULL if not found*/ +LIBETPAN_EXPORT +int chash_get(chash * hash, + chashdatum * key, chashdatum * result); + +/* Removes the entry associated to this key if it is found in the hash table, + and returns its contents if not dupped (otherwise, pointer will be NULL + and len TRUE). If entry is not found both pointer and len will be NULL. */ +LIBETPAN_EXPORT +int chash_delete(chash * hash, + chashdatum * key, + chashdatum * oldvalue); + +/* Resizes the hash table to the passed size. */ +LIBETPAN_EXPORT +int chash_resize(chash * hash, unsigned int size); + +/* Returns an iterator to the first non-empty entry of the hash table */ +LIBETPAN_EXPORT +chashiter * chash_begin(chash * hash); + +/* Returns the next non-empty entry of the hash table */ +LIBETPAN_EXPORT +chashiter * chash_next(chash * hash, chashiter * iter); + +/* Some of the following routines can be implemented as macros to + be faster. If you don't want it, define NO_MACROS */ +#ifdef NO_MACROS +/* Returns the size of the hash table */ +LIBETPAN_EXPORT +unsigned int chash_size(chash * hash); + +/* Returns the number of entries in the hash table */ +LIBETPAN_EXPORT +unsigned int chash_count(chash * hash); + +/* Returns the key part of the entry pointed by the iterator */ +LIBETPAN_EXPORT +void chash_key(chashiter * iter, chashdatum * result); + +/* Returns the value part of the entry pointed by the iterator */ +LIBETPAN_EXPORT +void chash_value(chashiter * iter, chashdatum * result); + +#else +static inline unsigned int chash_size(chash * hash) +{ + return hash->size; +} + +static inline unsigned int chash_count(chash * hash) +{ + return hash->count; +} + +static inline void chash_key(chashiter * iter, chashdatum * result) +{ + * result = iter->key; +} + +static inline void chash_value(chashiter * iter, chashdatum * result) +{ + * result = iter->value; +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/cinthash.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/cinthash.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,255 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: cinthash.c,v 1.9 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifndef LIBETPAN_CONFIG_H +# include "libetpan-config.h" +#endif +#include <stdlib.h> +#include "cinthash.h" + +struct cinthash_list { + unsigned long hash; + void * data; + struct cinthash_list * next; +}; + +static struct cinthash_list HASH_LISTHEAD_NEW = { 0, NULL, NULL }; + +static inline int hash_list_add(cinthash_t * table, + unsigned long hash, void * data) +{ + struct cinthash_list * ht; + int index; + + index = hash % table->hashtable_size; + + ht = malloc(sizeof(struct cinthash_list)); + if (ht == NULL) + return -1; + + ht->hash = hash; + ht->data = data; + ht->next = table->table[index].next; + + table->table[index].next = ht; + + return 0; +} + +static inline void hash_list_free(struct cinthash_list * list) +{ + struct cinthash_list * cur; + struct cinthash_list * next; + + next = list; + while (next != NULL) { + cur = next; + next = cur->next; + free(cur); + } +} + +static inline int hash_list_remove(cinthash_t * table, unsigned long hash) +{ + struct cinthash_list * cur; + int index; + + index = hash % table->hashtable_size; + + for(cur = &table->table[index] ; cur->next != NULL ; cur = cur->next) { + if (cur->next->hash == hash) { + struct cinthash_list * hash_data; + + hash_data = cur->next; + cur->next = cur->next->next; + + free(hash_data); + + return 0; + } + } + + return -1; +} + +static inline void * hash_list_find(cinthash_t * table, unsigned long hash) +{ + struct cinthash_list * cur; + int index; + + index = hash % table->hashtable_size; + + for(cur = table->table[index].next ; cur != NULL ; cur = cur->next) { + if (cur->hash == hash) + return cur->data; + } + + return NULL; +} + +cinthash_t * cinthash_new(unsigned long hashtable_size) +{ + cinthash_t * ht; + unsigned long i; + + ht = malloc(sizeof(cinthash_t)); + if (ht == NULL) + return NULL; + + ht->table = malloc(sizeof(struct cinthash_list) * hashtable_size); + if (ht->table == NULL) + return NULL; + + ht->hashtable_size = hashtable_size; + ht->count = 0; + + for(i = 0 ; i < hashtable_size ; i++) + ht->table[i] = HASH_LISTHEAD_NEW; + + return ht; +} + +void cinthash_free(cinthash_t * table) +{ + unsigned long i; + + for(i = 0 ; i < table->hashtable_size ; i++) + hash_list_free(table->table[i].next); + + free(table->table); + + free(table); +} + +int cinthash_add(cinthash_t * table, unsigned long hash, void * data) +{ + int index; + + index = hash % table->hashtable_size; + + if (table->table[index].data == NULL) { + table->table[index].hash = hash; + table->table[index].data = data; + table->table[index].next = NULL; + + table->count ++; + + return 0; + } + else { + int r; + + r = hash_list_add(table, hash, data); + if (r == -1) + return -1; + + table->count ++; + + return 0; + } +} + +int cinthash_remove(cinthash_t * table, unsigned long hash) +{ + int index; + + index = hash % table->hashtable_size; + + if (table->table[index].hash == hash) { + table->table[index].hash = 0; + table->table[index].data = NULL; + + table->count --; + + return 0; + } + else { + int r; + + r = hash_list_remove(table, hash); + + table->count --; + + return 0; + } +} + +void * cinthash_find(cinthash_t * table, unsigned long hash) +{ + int index; + + index = hash % table->hashtable_size; + + if (table->table[index].hash == hash) + return table->table[index].data; + + return hash_list_find(table, hash); +} + +void cinthash_foreach_key(cinthash_t * table, + void (* func)(unsigned long, void *), + void * data) +{ + unsigned long index; + struct cinthash_list * cur; + + for(index = 0 ; index < table->hashtable_size ; index ++) { + if (table->table[index].data != NULL) { + func(table->table[index].hash, data); + for(cur = table->table[index].next ; cur != NULL ; cur = cur->next) + func(cur->hash, data); + } + } +} + +void cinthash_foreach_data(cinthash_t * table, + void (* func)(void *, void *), + void * data) +{ + unsigned long index; + struct cinthash_list * cur; + + for(index = 0 ; index < table->hashtable_size ; index ++) { + if (table->table[index].data != NULL) { + func(table->table[index].data, data); + for(cur = table->table[index].next ; cur != NULL ; cur = cur->next) + func(cur->data, data); + } + } +} Added: freeswitch/trunk/libs/libetpan/src/data-types/cinthash.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/cinthash.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,69 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: cinthash.h,v 1.6 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef CINTHASH_H + +#define CINTHASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct cinthash_t { + struct cinthash_list * table; + unsigned long hashtable_size ; + unsigned long count; +} cinthash_t; + +cinthash_t * cinthash_new(unsigned long hashtable_size); +void cinthash_free(cinthash_t * table); + +int cinthash_add(cinthash_t * table, unsigned long hash, void * data); +int cinthash_remove(cinthash_t * table, unsigned long hash); +void * cinthash_find(cinthash_t * table, unsigned long hash); + +void cinthash_foreach_key(cinthash_t * table, + void (* func)(unsigned long, void *), + void * data); + +void cinthash_foreach_data(cinthash_t * table, + void (* fun)(void *, void *), + void * data); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/clist.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/clist.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,273 @@ +/* + * libEtPan! -- a mail stuff library + * + * clist - Implements simple generic double-linked pointer lists + * + * Copyright (c) 1999-2005, Ga�l Roualland <gael.roualland@iname.com> + * interface changes - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: clist.c,v 1.10 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#ifndef LIBETPAN_CONFIG_H +# include "libetpan-config.h" +#endif + +#include "clist.h" + +clist * clist_new(void) { + clist * lst; + + lst = (clist *) malloc(sizeof(clist)); + if (!lst) return NULL; + + lst->first = lst->last = NULL; + lst->count = 0; + + return lst; +} + +void clist_free(clist * lst) { + clistcell * l1, * l2; + + l1 = lst->first; + while (l1) { + l2 = l1->next; + free(l1); + l1 = l2; + } + + free(lst); +} + +#ifdef NO_MACROS +int clist_isempty(clist * lst) { + return ((lst->first==lst->last) && (lst->last==NULL)); +} + +clistiter * clist_begin(clist * lst) { + return lst->first; +} + +clistiter * clist_end(clist * lst) { + return lst->last; +} + +clistiter * clist_next(clistiter * iter) { + if (iter) + return iter->next; + else + return NULL; +} + +clistiter * clist_previous(clistiter * iter) { + if (iter) + return iter->previous; + else + return NULL; +} + +void * clist_content(clistiter * iter) { + if (iter) + return iter->data; + else + return NULL; +} + +int clist_count(clist * lst) { + return lst->count; +} + +int clist_prepend(clist * lst, void * data) { + return clist_insert_before(lst, lst->first, data); +} + +int clist_append(clist * lst, void * data) { + return clist_insert_after(lst, lst->last, data); +} +#endif + +int clist_insert_before(clist * lst, clistiter * iter, void * data) { + clistcell * c; + + c = (clistcell *) malloc(sizeof(clistcell)); + if (!c) return -1; + + c->data = data; + lst->count++; + + if (clist_isempty(lst)) { + c->previous = c->next = NULL; + lst->first = lst->last = c; + return 0; + } + + if (!iter) { + c->previous = lst->last; + c->previous->next = c; + c->next = NULL; + lst->last = c; + return 0; + } + + c->previous = iter->previous; + c->next = iter; + c->next->previous = c; + if (c->previous) + c->previous->next = c; + else + lst->first = c; + + return 0; +} + +int clist_insert_after(clist * lst, clistiter * iter, void * data) { + clistcell * c; + + c = (clistcell *) malloc(sizeof(clistcell)); + if (!c) return -1; + + c->data = data; + lst->count++; + + if (clist_isempty(lst)) { + c->previous = c->next = NULL; + lst->first = lst->last = c; + return 0; + } + + if (!iter) { + c->previous = lst->last; + c->previous->next = c; + c->next = NULL; + lst->last = c; + return 0; + } + + c->previous = iter; + c->next = iter->next; + if (c->next) + c->next->previous = c; + else + lst->last = c; + c->previous->next = c; + + return 0; +} + +clistiter * clist_delete(clist * lst, clistiter * iter) { + clistiter * ret; + + if (!iter) return NULL; + + if (iter->previous) + iter->previous->next = iter->next; + else + lst->first = iter->next; + + if (iter->next) { + iter->next->previous = iter->previous; + ret = iter->next; + } else { + lst->last = iter->previous; + ret = NULL; + } + + free(iter); + lst->count--; + + return ret; +} + + + +void clist_foreach(clist * lst, clist_func func, void * data) +{ + clistiter * cur; + + for(cur = clist_begin(lst) ; cur != NULL ; cur = cur->next) + func(cur->data, data); +} + +void clist_concat(clist * dest, clist * src) +{ + if (src->first == NULL) { + /* do nothing */ + } + else if (dest->last == NULL) { + dest->first = src->first; + dest->last = src->last; + } + else { + dest->last->next = src->first; + src->first->previous = dest->last; + dest->last = src->last; + } + + dest->count += src->count; + src->last = src->first = NULL; +} + +static inline clistiter * internal_clist_nth(clist * lst, int index) +{ + clistiter * cur; + + cur = clist_begin(lst); + while ((index > 0) && (cur != NULL)) { + cur = cur->next; + index --; + } + + if (cur == NULL) + return NULL; + + return cur; +} + +void * clist_nth_data(clist * lst, int index) +{ + clistiter * cur; + + cur = internal_clist_nth(lst, index); + if (cur == NULL) + return NULL; + + return cur->data; +} + +clistiter * clist_nth(clist * lst, int index) +{ + return internal_clist_nth(lst, index); +} Added: freeswitch/trunk/libs/libetpan/src/data-types/clist.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/clist.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,133 @@ +/* + * libEtPan! -- a mail stuff library + * + * clist - Implements simple generic double-linked pointer lists + * + * Copyright (c) 1999-2005, Ga�l Roualland <gael.roualland@iname.com> + * interface changes - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: clist.h,v 1.10 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef CLIST_H +#define CLIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct clistcell_s { + void * data; + struct clistcell_s * previous; + struct clistcell_s * next; +} clistcell; + +struct clist_s { + clistcell * first; + clistcell * last; + int count; +}; + +typedef struct clist_s clist; +typedef clistcell clistiter; + +/* Allocate a new pointer list */ +clist * clist_new(void); + +/* Destroys a list. Data pointed by data pointers is NOT freed. */ +void clist_free(clist *); + +/* Some of the following routines can be implemented as macros to + be faster. If you don't want it, define NO_MACROS */ +#ifdef NO_MACROS + +/* Returns TRUE if list is empty */ +int clist_isempty(clist *); + +/* Returns the number of elements in the list */ +int clist_count(clist *); + +/* Returns an iterator to the first element of the list */ +clistiter * clist_begin(clist *); + +/* Returns an iterator to the last element of the list */ +clistiter * clist_end(clist *); + +/* Returns an iterator to the next element of the list */ +clistiter * clist_next(clistiter *); + +/* Returns an iterator to the previous element of the list */ +clistiter * clist_previous(clistiter *); + +/* Returns the data pointer of this element of the list */ +void* clist_content(clistiter *); + +/* Inserts this data pointer at the beginning of the list */ +int clist_prepend(clist *, void *); + +/* Inserts this data pointer at the end of the list */ +int clist_append(clist *, void *); +#else +#define clist_isempty(lst) ((lst->first==lst->last) && (lst->last==NULL)) +#define clist_count(lst) (lst->count) +#define clist_begin(lst) (lst->first) +#define clist_end(lst) (lst->last) +#define clist_next(iter) (iter ? iter->next : NULL) +#define clist_previous(iter) (iter ? iter->previous : NULL) +#define clist_content(iter) (iter ? iter->data : NULL) +#define clist_prepend(lst, data) (clist_insert_before(lst, lst->first, data)) +#define clist_append(lst, data) (clist_insert_after(lst, lst->last, data)) +#endif + +/* Inserts this data pointer before the element pointed by the iterator */ +int clist_insert_before(clist *, clistiter *, void *); + +/* Inserts this data pointer after the element pointed by the iterator */ +int clist_insert_after(clist *, clistiter *, void *); + +/* Deletes the element pointed by the iterator. + Returns an iterator to the next element. */ +clistiter * clist_delete(clist *, clistiter *); + +typedef void (* clist_func)(void *, void *); + +void clist_foreach(clist * lst, clist_func func, void * data); + +void clist_concat(clist * dest, clist * src); + +void * clist_nth_data(clist * lst, int index); + +clistiter * clist_nth(clist * lst, int index); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/connect.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/connect.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,141 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: connect.c,v 1.16 2006/07/15 12:24:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "connect.h" + +#include <sys/types.h> +#include <string.h> +#include <stdio.h> + +#ifdef _MSC_VER +# include "win_etpan.h" +#else +# include <netdb.h> +# include <netinet/in.h> +# include <sys/socket.h> +# include <unistd.h> +#endif + +uint16_t mail_get_service_port(const char * name, char * protocol) +{ + struct servent * service; + + service = getservbyname(name, protocol); + + if (service == NULL) + return 0; + + return ntohs(service->s_port); +} + +int mail_tcp_connect(const char * server, uint16_t port) +{ +#ifndef HAVE_IPV6 + struct hostent * remotehost; + struct sockaddr_in sa; +#else /* HAVE_IPV6 */ + struct addrinfo hints, *res, *ai; + char port_str[6]; +#endif +#ifdef WIN32 + SOCKET s; +#else + int s; +#endif + int r; + +#ifndef HAVE_IPV6 + s = socket(PF_INET, SOCK_STREAM, 0); + if (s == -1) + goto err; + + remotehost = gethostbyname(server); + if (remotehost == NULL) + goto close_socket; + + sa.sin_family = AF_INET; + sa.sin_port = htons(port); + memcpy(&sa.sin_addr, remotehost->h_addr, remotehost->h_length); + + r = connect(s, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)); + if (r == -1) + goto close_socket; +#else /* HAVE_IPV6 */ + memset(&hints, 0, sizeof(hints)); + + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + /* convert port from integer to string. */ + snprintf(port_str, sizeof(port_str), "%d", port); + + if (getaddrinfo(server, port_str, &hints, &res) != 0) + goto err; + + for (ai = res; ai != NULL; ai = ai->ai_next) { + s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (s == -1) + continue; + + r = connect(s, ai->ai_addr, ai->ai_addrlen); + if (r == 0) + break; + } + + if (res != NULL) + freeaddrinfo(res); + + if (ai == NULL) + goto err; +#endif + + return s; + +#ifndef HAVE_IPV6 + close_socket: +#ifdef WIN32 + closesocket(s); +#else + close(s); +#endif +#endif + err: + return -1; +} Added: freeswitch/trunk/libs/libetpan/src/data-types/connect.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/connect.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: connect.h,v 1.15 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef CONNECT_H + +#define CONNECT_H + +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +uint16_t mail_get_service_port(const char * name, char * protocol); +int mail_tcp_connect(const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif + Added: freeswitch/trunk/libs/libetpan/src/data-types/hmac-md5.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/hmac-md5.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,94 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* hmac-md5.h -- HMAC_MD5 functions + */ + +/* + * $Id: hmac-md5.h,v 1.4 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef HMAC_MD5_H +#define HMAC_MD5_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#define HMAC_MD5_SIZE 16 + +/* intermediate MD5 context */ +typedef struct HMAC_MD5_CTX_s { + MD5_CTX ictx, octx; +} HMAC_MD5_CTX; + +/* intermediate HMAC state + * values stored in network byte order (Big Endian) + */ +typedef struct HMAC_MD5_STATE_s { + UINT4 istate[4]; + UINT4 ostate[4]; +} HMAC_MD5_STATE; + +/* One step hmac computation + * + * digest may be same as text or key + */ +void hmac_md5(const unsigned char *text, int text_len, + const unsigned char *key, int key_len, + unsigned char digest[HMAC_MD5_SIZE]); + +/* create context from key + */ +void hmac_md5_init(HMAC_MD5_CTX *hmac, + const unsigned char *key, int key_len); + +/* precalculate intermediate state from key + */ +void hmac_md5_precalc(HMAC_MD5_STATE *hmac, + const unsigned char *key, int key_len); + +/* initialize context from intermediate state + */ +void hmac_md5_import(HMAC_MD5_CTX *hmac, HMAC_MD5_STATE *state); + +#define hmac_md5_update(hmac, text, text_len) MD5Update(&(hmac)->ictx, (text), (text_len)) + +/* finish hmac from intermediate result. Intermediate result is zeroed. + */ +void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE], + HMAC_MD5_CTX *hmac); + +#ifdef __cplusplus +} +#endif + +#endif /* HMAC_MD5_H */ Added: freeswitch/trunk/libs/libetpan/src/data-types/mail.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mail.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mail.h,v 1.8 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAIL_H + +#define MAIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/mail_cache_db.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mail_cache_db.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,500 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mail_cache_db.c,v 1.20 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mail_cache_db.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> + +#include "libetpan-config.h" + +#include "maillock.h" + +#if DBVERS >= 1 +#include <db.h> +#endif + +#if DBVERS >= 1 +static struct mail_cache_db * mail_cache_db_new(DB * db) +{ + struct mail_cache_db * cache_db; + + cache_db = malloc(sizeof(* cache_db)); + if (cache_db == NULL) + return NULL; + cache_db->internal_database = db; + + return cache_db; +} + +static void mail_cache_db_free(struct mail_cache_db * cache_db) +{ + free(cache_db); +} +#endif + +int mail_cache_db_open(const char * filename, + struct mail_cache_db ** pcache_db) +{ +#if DBVERS >= 1 + DB * dbp; +#if DBVERS > 1 + int r; +#endif + struct mail_cache_db * cache_db; + +#if DB_VERSION_MAJOR >= 3 + r = db_create(&dbp, NULL, 0); + if (r != 0) + goto err; + +#if (DB_VERSION_MAJOR >= 4) && ((DB_VERSION_MAJOR > 4) || (DB_VERSION_MINOR >= 1)) + r = dbp->open(dbp, NULL, filename, NULL, DB_BTREE, DB_CREATE, + S_IRUSR | S_IWUSR); +#else + r = dbp->open(dbp, filename, NULL, DB_BTREE, DB_CREATE, S_IRUSR | S_IWUSR); +#endif + if (r != 0) + goto close_db; +#else +#if DBVERS > 1 + r = db_open(filename, DB_BTREE, DB_CREATE, S_IRUSR | S_IWUSR, + NULL, NULL, &dbp); + if (r != 0) + goto err; +#elif DBVERS == 1 + dbp = dbopen(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, DB_BTREE, NULL); + if (dbp == NULL) + goto err; +#else + goto err; +#endif +#endif + + cache_db = mail_cache_db_new(dbp); + if (cache_db == NULL) + goto close_db; + + * pcache_db = cache_db; + + return 0; + + close_db: +#if DBVERS > 1 + dbp->close(dbp, 0); +#elif DBVERS == 1 + dbp->close(dbp); +#endif + err: + return -1; +#else + return -1; +#endif +} + +void mail_cache_db_close(struct mail_cache_db * cache_db) +{ +#if DBVERS >= 1 + DB * dbp; + + dbp = cache_db->internal_database; + +#if DBVERS > 1 + dbp->close(cache_db->internal_database, 0); +#elif DBVERS == 1 + dbp->close(cache_db->internal_database); +#endif + + mail_cache_db_free(cache_db); +#endif +} + +int mail_cache_db_open_lock(const char * filename, + struct mail_cache_db ** pcache_db) +{ + int r; + struct mail_cache_db * cache_db; + + r = maillock_write_lock(filename, -1); + if (r < 0) + goto err; + + r = mail_cache_db_open(filename, &cache_db); + if (r < 0) + goto unlock; + + * pcache_db = cache_db; + + return 0; + + unlock: + maillock_write_unlock(filename, -1); + err: + return -1; +} + +void mail_cache_db_close_unlock(const char * filename, + struct mail_cache_db * cache_db) +{ + mail_cache_db_close(cache_db); + maillock_write_unlock(filename, -1); +} + + +int mail_cache_db_put(struct mail_cache_db * cache_db, + const void * key, size_t key_len, const void * value, size_t value_len) +{ +#if DBVERS >= 1 + int r; + DBT db_key; + DBT db_data; + DB * dbp; + + dbp = cache_db->internal_database; + + memset(&db_key, 0, sizeof(db_key)); + memset(&db_data, 0, sizeof(db_data)); + db_key.data = (void *) key; + db_key.size = key_len; + db_data.data = (void *) value; + db_data.size = value_len; + +#if DBVERS > 1 + r = dbp->put(dbp, NULL, &db_key, &db_data, 0); +#elif DBVERS == 1 + r = dbp->put(dbp, &db_key, &db_data, 0); +#else + r = -1; +#endif + if (r != 0) + return -1; + + return 0; +#else + return -1; +#endif +} + +int mail_cache_db_get(struct mail_cache_db * cache_db, + const void * key, size_t key_len, void ** pvalue, size_t * pvalue_len) +{ +#if DBVERS >= 1 + int r; + DBT db_key; + DBT db_data; + DB * dbp; + + dbp = cache_db->internal_database; + + memset(&db_key, 0, sizeof(db_key)); + memset(&db_data, 0, sizeof(db_data)); + db_key.data = (void *) key; + db_key.size = key_len; + +#if DBVERS > 1 + r = dbp->get(dbp, NULL, &db_key, &db_data, 0); +#elif DBVERS == 1 + r = dbp->get(dbp, &db_key, &db_data, 0); +#else + r = -1; +#endif + + if (r != 0) + return -1; + + * pvalue = db_data.data; + * pvalue_len = db_data.size; + + return 0; +#else + return -1; +#endif +} + +int mail_cache_db_del(struct mail_cache_db * cache_db, + const void * key, size_t key_len) +{ +#if DBVERS >= 1 + int r; + DBT db_key; + DB * dbp; + + dbp = cache_db->internal_database; + + memset(&db_key, 0, sizeof(db_key)); + db_key.data = (void *) key; + db_key.size = key_len; + +#if DBVERS > 1 + r = dbp->del(dbp, NULL, &db_key, 0); +#elif DBVERS == 1 + r = dbp->del(dbp, &db_key, 0); +#else + r = -1; +#endif + if (r != 0) + return -1; + + return 0; +#else + return -1; +#endif +} + +#if DBVERS > 1 +int mail_cache_db_clean_up(struct mail_cache_db * cache_db, + chash * exist) +{ + DB * dbp; + int r; + DBC * dbcp; + DBT db_key; + DBT db_data; + + dbp = cache_db->internal_database; + +#if DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR < 6 + r = dbp->cursor(dbp, NULL, &dbcp); +#else + r = dbp->cursor(dbp, NULL, &dbcp, 0); +#endif + if (r != 0) + return -1; + + memset(&db_key, 0, sizeof(db_key)); + memset(&db_data, 0, sizeof(db_data)); + + while (1) { + chashdatum hash_key; + chashdatum hash_data; + + r = dbcp->c_get(dbcp, &db_key, &db_data, DB_NEXT); + if (r != 0) + break; + + hash_key.data = db_key.data; + hash_key.len = db_key.size; + + r = chash_get(exist, &hash_key, &hash_data); + if (r < 0) { + r = dbcp->c_del(dbcp, 0); + if (r != 0) + return -1; + } + } + + r = dbcp->c_close(dbcp); + if (r != 0) + return -1; + + return 0; +} +#elif DBVERS == 1 +int mail_cache_db_clean_up(struct mail_cache_db * cache_db, + chash * exist) +{ + DB * dbp; + int r; + DBT db_key; + DBT db_data; + + dbp = cache_db->internal_database; + + r = dbp->seq(dbp, &db_key, &db_data, R_FIRST); + if (r == -1) + return -1; + + while (r == 0) { + chashdatum hash_key; + chashdatum hash_data; + + hash_key.data = db_key.data; + hash_key.len = db_key.size; + + r = chash_get(exist, &hash_key, &hash_data); + if (r < 0) { + r = dbp->del(dbp, &db_key, 0); + if (r != 0) + return -1; + } + + r = dbp->seq(dbp, &db_key, &db_data, R_NEXT); + if (r < 0) + return -1; + } + + return 0; +} +#else +int mail_cache_db_clean_up(struct mail_cache_db * cache_db, + chash * exist) +{ + return -1; +} +#endif + +int mail_cache_db_get_size(struct mail_cache_db * cache_db, + const void * key, size_t key_len, size_t * pvalue_len) +{ +#if DBVERS >= 1 + int r; + DBT db_key; + DBT db_data; + DB * dbp; + + dbp = cache_db->internal_database; + + memset(&db_key, 0, sizeof(db_key)); + memset(&db_data, 0, sizeof(db_data)); + db_key.data = (void *) key; + db_key.size = key_len; +#if DBVERS > 1 + db_data.flags = DB_DBT_USERMEM; + db_data.ulen = 0; +#endif + +#if DBVERS > 1 + r = dbp->get(dbp, NULL, &db_key, &db_data, 0); +#elif DBVERS == 1 + r = dbp->get(dbp, &db_key, &db_data, 0); +#else + r = -1; +#endif + + if (r != 0) + return -1; + + * pvalue_len = db_data.size; + + return 0; +#else + return -1; +#endif +} + +#if DBVERS > 1 +int mail_cache_db_get_keys(struct mail_cache_db * cache_db, + chash * keys) +{ + DB * dbp; + int r; + DBC * dbcp; + DBT db_key; + DBT db_data; + + dbp = cache_db->internal_database; + + r = dbp->cursor(dbp, NULL, &dbcp, 0); + if (r != 0) + return -1; + + memset(&db_key, 0, sizeof(db_key)); + memset(&db_data, 0, sizeof(db_data)); + + while (1) { + chashdatum hash_key; + chashdatum hash_data; + + r = dbcp->c_get(dbcp, &db_key, &db_data, DB_NEXT); + if (r != 0) + break; + + hash_key.data = db_key.data; + hash_key.len = db_key.size; + hash_data.data = NULL; + hash_data.len = 0; + + r = chash_set(keys, &hash_key, &hash_data, NULL); + if (r < 0) { + return -1; + } + } + + r = dbcp->c_close(dbcp); + if (r != 0) + return -1; + + return 0; +} +#elif DBVERS == 1 +int mail_cache_db_get_keys(struct mail_cache_db * cache_db, + chash * keys) +{ + DB * dbp; + int r; + DBT db_key; + DBT db_data; + + dbp = cache_db->internal_database; + + r = dbp->seq(dbp, &db_key, &db_data, R_FIRST); + if (r == -1) + return -1; + + while (r == 0) { + chashdatum hash_key; + chashdatum hash_data; + + hash_key.data = db_key.data; + hash_key.len = db_key.size; + hash_data.data = NULL; + hash_data.len = 0; + + r = chash_set(keys, &hash_key, &hash_data, NULL); + if (r < 0) { + return -1; + } + + r = dbp->seq(dbp, &db_key, &db_data, R_NEXT); + if (r < 0) + return -1; + } + + return 0; +} +#else +int mail_cache_db_get_keys(struct mail_cache_db * cache_db, + chash * keys) +{ + return -1; +} +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/mail_cache_db.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mail_cache_db.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,158 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mail_cache_db.h,v 1.6 2005/04/07 00:05:25 hoa Exp $ + */ + +#ifndef MAIL_CACHE_DB_H + +#define MAIL_CACHE_DB_H + +#include <sys/types.h> +#include "mail_cache_db_types.h" +#include "chash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + this module will handle a database "f(key) -> value" in a file + + berkeley DB or other can be used for implementation of low-level file. +*/ + +/* + mail_cache_db_open() + + This function opens the file "filename". + The pointer return in pcache_db should be used for further references + to the database. +*/ + +int mail_cache_db_open(const char * filename, + struct mail_cache_db ** pcache_db); + +/* + mail_cache_db_close() + + This function closes the opened database. + The pointer cannot be used later. +*/ + +void mail_cache_db_close(struct mail_cache_db * cache_db); + +/* + mail_cache_db_open_lock() + + This function opens and locks the file "filename". + The pointer return in pcache_db should be used for further references + to the database. +*/ + +int mail_cache_db_open_lock(const char * filename, + struct mail_cache_db ** pcache_db); + +/* + mail_cache_db_open_unlock() + + This function closes and unlocks the opened database. + The pointer cannot be used later. +*/ + +void mail_cache_db_close_unlock(const char * filename, + struct mail_cache_db * cache_db); + +/* + mail_cache_db_put() + + This function will store a given key and value in the database. +*/ + +int mail_cache_db_put(struct mail_cache_db * cache_db, + const void * key, size_t key_len, const void * value, size_t value_len); + +/* + mail_cache_db_get() + + This function will retrieve the value corresponding to a given key + from the database. +*/ + +int mail_cache_db_get(struct mail_cache_db * cache_db, + const void * key, size_t key_len, void ** pvalue, size_t * pvalue_len); + +/* + mail_cache_db_get_size() + + This function will retrieve the size of the value corresponding + to a given key from the database. +*/ + +int mail_cache_db_get_size(struct mail_cache_db * cache_db, + const void * key, size_t key_len, size_t * pvalue_len); + +/* + mail_cache_db_del() + + This function will delete the given key and the corresponding value + from the database. +*/ + +int mail_cache_db_del(struct mail_cache_db * cache_db, + const void * key, size_t key_len); + +/* + mail_cache_clean_up() + + This function will delete the key all the key/value pairs of the + database file which key does not exist in the given hash. +*/ + +int mail_cache_db_clean_up(struct mail_cache_db * cache_db, + chash * exist); + +/* + mail_cache_db_get_keys() + + This function will get all keys of the database and will + store them to the given chash. +*/ + +int mail_cache_db_get_keys(struct mail_cache_db * cache_db, + chash * keys); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/mail_cache_db_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mail_cache_db_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mail_cache_db_types.h,v 1.2 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAIL_CACHE_DB_TYPES_H + +#define MAIL_CACHE_DB_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct mail_cache_db { + void * internal_database; +}; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/maillock.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/maillock.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,356 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maillock.c,v 1.15 2006/08/05 02:34:06 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "maillock.h" + +#include "libetpan-config.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <stdio.h> +#include <time.h> +#include <string.h> +#ifdef _MSC_VER +# include "win_etpan.h" +#endif +#ifdef HAVE_LIBLOCKFILE +#include <lockfile.h> +#endif + +/* ********************************************************************** */ + +/* lock primitives */ + +/* the lock code is modified from the dot lock file code from mail.local.c */ + +/* + SENDMAIL LICENSE + +The following license terms and conditions apply, unless a different +license is obtained from Sendmail, Inc., 6425 Christie Ave, Fourth Floor, +Emeryville, CA 94608, or by electronic mail at license@sendmail.com. + +License Terms: + +Use, Modification and Redistribution (including distribution of any +modified or derived work) in source and binary forms is permitted only if +each of the following conditions is met: + +1. Redistributions qualify as "freeware" or "Open Source Software" under + one of the following terms: + + (a) Redistributions are made at no charge beyond the reasonable cost of + materials and delivery. + + (b) Redistributions are accompanied by a copy of the Source Code or by an + irrevocable offer to provide a copy of the Source Code for up to three + years at the cost of materials and delivery. Such redistributions + must allow further use, modification, and redistribution of the Source + Code under substantially the same terms as this license. For the + purposes of redistribution "Source Code" means the complete compilable + and linkable source code of sendmail including all modifications. + +2. Redistributions of source code must retain the copyright notices as they + appear in each source code file, these license terms, and the + disclaimer/limitation of liability set forth as paragraph 6 below. + +3. Redistributions in binary form must reproduce the Copyright Notice, + these license terms, and the disclaimer/limitation of liability set + forth as paragraph 6 below, in the documentation and/or other materials + provided with the distribution. For the purposes of binary distribution + the "Copyright Notice" refers to the following language: + "Copyright (c) 1998-2002 Sendmail, Inc. All rights reserved." + +4. Neither the name of Sendmail, Inc. nor the University of California nor + the names of their contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. The name "sendmail" is a trademark of Sendmail, Inc. + +5. All redistributions must comply with the conditions imposed by the + University of California on certain embedded code, whose copyright + notice and conditions for redistribution are as follows: + + (a) Copyright (c) 1988, 1993 The Regents of the University of + California. All rights reserved. + + (b) Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + (i) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (ii) Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + (iii) Neither the name of the University nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +6. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY + SENDMAIL, INC. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + NO EVENT SHALL SENDMAIL, INC., THE REGENTS OF THE UNIVERSITY OF + CALIFORNIA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. +*/ + +/* + TODO : lock, prefer fcntl() over flock() + AND use dotlock code above +*/ + +#define LOCKTO_RM 300 /* timeout for stale lockfile removal */ +#define LOCKTO_GLOB 400 /* global timeout for lockfile creation */ + +#ifdef WIN32 +# define F_RDLCK 0 +# define F_WRLCK 1 +# include <sys/locking.h> +#endif + +static int lock_common(const char * filename, int fd, short locktype) +{ +#ifdef WIN32 + time_t start; + + /* SEB try implementation */ + if (fd != -1) { + lseek( fd, 0L, SEEK_SET ); + if (_locking( fd, _LK_NBLCK, LONG_MAX) == 0) return 0; + + time(&start); + + while (1) { + time_t now; + sleep( 5); + if (_locking( fd, _LK_NBLCK, LONG_MAX) == 0) return 0; + time(&now); + if (now > start + LOCKTO_GLOB) { + return -1; + } + } + } + +#else + char lockfilename[PATH_MAX]; +#ifndef HAVE_LIBLOCKFILE + struct flock lock; + /* dot lock file */ + int statfailed = 0; + time_t start; + int r; +#endif + int res; + + /* dot lock file */ + + if (strlen(filename) + 6 > PATH_MAX) { + res = -1; + goto err; + } + + snprintf(lockfilename, PATH_MAX, "%s.lock", filename); + +#ifdef HAVE_LIBLOCKFILE + return lockfile_create(lockfilename, LOCKTO_GLOB, 0); +#else + + if (fd != -1) { + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = getpid(); + lock.l_type = locktype; + lock.l_whence = SEEK_SET; + + r = fcntl(fd, F_SETLKW, &lock); + if (r < 0) { + /* WARNING POSIX lock could not be applied */ + } + } + + time(&start); + while (1) { + int fd; + struct stat st; + time_t now; + + /* global timeout */ + time(&now); + if (now > start + LOCKTO_GLOB) { + res = -1; + goto unlock; + } + + fd = open(lockfilename, O_WRONLY|O_EXCL|O_CREAT, 0); + if (fd >= 0) { + /* defeat lock checking programs which test pid */ + write(fd, "0", 2); + close(fd); + break; + } + + /* libEtPan! - adds a delay of 5 seconds between each tries */ + sleep(5); + + if (stat(lockfilename, &st) < 0) { + if (statfailed++ > 5) { + res = -1; + goto unlock; + } + continue; + } + statfailed = 0; + time(&now); + + if (now < st.st_ctime + LOCKTO_RM) + continue; + + /* try to remove stale lockfile */ + if (unlink(lockfilename) < 0) { + res = -1; + goto unlock; + } + + /* + libEtPan! - removes this delay of 5 seconds, + maybe it was misplaced ? + */ +#if 0 + sleep(5); +#endif + } + + return 0; + + unlock: + if (fd != -1) { + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = getpid(); + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + + r = fcntl(fd, F_SETLK, &lock); + if (r < 0) { + /* WARNING POSIX lock could not be applied */ + } + } +#endif + err: + return res; +#endif /* WIN32 */ +} + +static int unlock_common(const char * filename, int fd) +{ +/* SEB */ +#ifdef WIN32 + if (fd != -1) { + lseek( fd, 0L, SEEK_SET ); + _locking( fd, _LK_UNLCK, LONG_MAX); + } + return 0; +#else + char lockfilename[PATH_MAX]; +#ifndef HAVE_LIBLOCKFILE + struct flock lock; + int r; +#endif + + if (strlen(filename) + 6 > PATH_MAX) + return -1; + + snprintf(lockfilename, PATH_MAX, "%s.lock", filename); + +#ifdef HAVE_LIBLOCKFILE + return lockfile_remove(lockfilename); +#else + + unlink(lockfilename); + + if (fd != -1) { + lock.l_start = 0; + lock.l_len = 0; + lock.l_pid = getpid(); + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + + r = fcntl(fd, F_SETLK, &lock); + if (r < 0) { + /* WARNING POSIX lock could not be applied */ + } + } + + return 0; +#endif +#endif /* WIN32 */ +} + +int maillock_read_lock(const char * filename, int fd) +{ + return lock_common(filename, fd, F_RDLCK); +} + +int maillock_read_unlock(const char * filename, int fd) +{ + return unlock_common(filename, fd); +} + +int maillock_write_lock(const char * filename, int fd) +{ + return lock_common(filename, fd, F_WRLCK); +} + +int maillock_write_unlock(const char * filename, int fd) +{ + return unlock_common(filename, fd); +} Added: freeswitch/trunk/libs/libetpan/src/data-types/maillock.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/maillock.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maillock.h,v 1.5 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAILLOCK_H + +#define MAILLOCK_H + +#ifdef __cplusplus +extern "C" { +#endif + +int maillock_read_lock(const char * filename, int fd); +int maillock_read_unlock(const char * filename, int fd); +int maillock_write_lock(const char * filename, int fd); +int maillock_write_unlock(const char * filename, int fd); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/mailsasl.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mailsasl.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,71 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailsasl.h" + +#ifdef USE_SASL + +#ifdef LIBETPAN_REENTRANT +#include <pthread.h> +#endif +#include <sasl/sasl.h> + +#ifdef LIBETPAN_REENTRANT +static pthread_mutex_t sasl_lock = PTHREAD_MUTEX_INITIALIZER; +#endif +static int sasl_use_count = 0; + +void mailsasl_external_ref(void) +{ +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&sasl_lock); +#endif + sasl_use_count ++; +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&sasl_lock); +#endif +} + +void mailsasl_ref(void) +{ +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&sasl_lock); +#endif + sasl_use_count ++; + if (sasl_use_count == 1) + sasl_client_init(NULL); +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&sasl_lock); +#endif +} + +void mailsasl_unref(void) +{ +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&sasl_lock); +#endif + sasl_use_count --; + if (sasl_use_count == 0) { + sasl_done(); + } +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&sasl_lock); +#endif +} + +#else + +void mailsasl_external_ref(void) +{ +} + +void mailsasl_ref(void) +{ +} + +void mailsasl_unref(void) +{ +} + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/mailsasl.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mailsasl.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,11 @@ +#ifndef MAILSASL_H + +#define MAILSASL_H + +/* if Cyrus-SASL is used outside of libetpan */ +void mailsasl_external_ref(void); + +void mailsasl_ref(void); +void mailsasl_unref(void); + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/mailsem.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mailsem.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,322 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsem.c,v 1.11 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailsem.h" +#include <stdlib.h> +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#include <unistd.h> + +#ifdef LIBETPAN_REENTRANT +#include <pthread.h> +#include <semaphore.h> +#endif + +struct mailsem_internal { + /* Current count of the semaphore. */ + unsigned int count; + + /* Number of threads that have called <sema_wait>. */ + unsigned long waiters_count; + +#ifdef LIBETPAN_REENTRANT + /* Serialize access to <count> and <waiters_count>. */ + pthread_mutex_t lock; + + /* Condition variable that blocks the <count> 0. */ + pthread_cond_t count_nonzero; +#endif +}; + +static int mailsem_internal_init(struct mailsem_internal * s, + unsigned int initial_count) +{ +#ifdef LIBETPAN_REENTRANT + int r; + + r = pthread_mutex_init(&s->lock, NULL); + if (r != 0) + goto err; + + r = pthread_cond_init(&s->count_nonzero, NULL); + if (r != 0) + goto destroy_mutex; + + s->count = initial_count; + s->waiters_count = 0; + + return 0; + + destroy_mutex: + pthread_mutex_destroy(&s->lock); + err: + return -1; +#else + return -1; +#endif +} + +static void mailsem_internal_destroy(struct mailsem_internal * s) +{ +#ifdef LIBETPAN_REENTRANT + pthread_cond_destroy(&s->count_nonzero); + pthread_mutex_destroy(&s->lock); +#endif +} + +int mailsem_internal_wait(struct mailsem_internal * s) +{ +#ifdef LIBETPAN_REENTRANT + int r; + + /* Acquire mutex to enter critical section. */ + r = pthread_mutex_lock(&s->lock); + if (r != 0) + goto err; + + /* Keep track of the number of waiters so that <sema_post> works correctly. */ + s->waiters_count ++; + + /* Wait until the semaphore count is > 0, then atomically release */ + /* <lock> and wait for <count_nonzero> to be signaled. */ + while (s->count == 0) { + r = pthread_cond_wait(&s->count_nonzero, &s->lock); + if (r != 0) + goto unlock; + } + + /* <s->lock> is now held. */ + + /* Decrement the waiters count. */ + s->waiters_count --; + + /* Decrement the semaphore's count. */ + s->count --; + + /* Release mutex to leave critical section. */ + pthread_mutex_unlock(&s->lock); + + return 0; + + unlock: + pthread_mutex_unlock(&s->lock); + err: + return -1; +#else + return -1; +#endif +} + +static int mailsem_internal_post(struct mailsem_internal * s) +{ +#ifdef LIBETPAN_REENTRANT + int r; + + r = pthread_mutex_lock(&s->lock); + if (r != 0) + goto err; + + /* Always allow one thread to continue if it is waiting. */ + if (s->waiters_count > 0) { + r = pthread_cond_signal(&s->count_nonzero); + if (r != 0) + goto unlock; + } + + /* Increment the semaphore's count. */ + s->count ++; + + pthread_mutex_unlock(&s->lock); + + return 0; + + unlock: + pthread_mutex_unlock(&s->lock); + err: + return -1; +#else + return -1; +#endif +} + +enum { + SEMKIND_SEMOPEN, + SEMKIND_SEMINIT, + SEMKIND_INTERNAL +}; + +#if 0 +#define SEMNAME_LEN 64 + +struct mailsem * mailsem_new(void) +{ +#ifdef LIBETPAN_REENTRANT + struct mailsem * sem; + int r; + + sem = malloc(sizeof(* sem)); + if (sem == NULL) + goto err; + + sem->sem_sem = malloc(sizeof(sem_t)); + if (sem->sem_sem == NULL) + goto free_sem; + + r = sem_init(sem->sem_sem, 0, 0); + if (r < 0) { + char name[SEMNAME_LEN]; + pid_t pid; + + free(sem->sem_sem); + + pid = getpid(); + snprintf(name, sizeof(name), "sem-%p-%i", sem, pid); + +#ifndef __CYGWIN__ + sem->sem_sem = sem_open(name, O_CREAT | O_EXCL, 0700, 0); + if (sem->sem_sem == (sem_t *) SEM_FAILED) + goto free_sem; + + sem->sem_kind = SEMKIND_SEMOPEN; +#else + goto free_sem; +#endif + } + else { + sem->sem_kind = SEMKIND_SEMINIT; + } + + return sem; + + free_sem: + free(sem); + err: + return NULL; +#else + return NULL; +#endif +} + +void mailsem_free(struct mailsem * sem) +{ +#ifdef LIBETPAN_REENTRANT + if (sem->sem_kind == SEMKIND_SEMOPEN) { + char name[SEMNAME_LEN]; + pid_t pid; + + pid = getpid(); + +#ifndef __CYGWIN__ + sem_close((sem_t *) sem->sem_sem); + snprintf(name, sizeof(name), "sem-%p-%i", sem, pid); + sem_unlink(name); +#endif + } + else { + sem_destroy((sem_t *) sem->sem_sem); + free(sem->sem_sem); + } + free(sem); +#endif +} + +int mailsem_up(struct mailsem * sem) +{ +#ifdef LIBETPAN_REENTRANT + return sem_post((sem_t *) sem->sem_sem); +#else + return -1; +#endif +} + +int mailsem_down(struct mailsem * sem) +{ +#ifdef LIBETPAN_REENTRANT + return sem_wait((sem_t *) sem->sem_sem); +#else + return -1; +#endif +} +#endif + +struct mailsem * mailsem_new(void) +{ + struct mailsem * sem; + int r; + + sem = malloc(sizeof(* sem)); + if (sem == NULL) + goto err; + + sem->sem_sem = malloc(sizeof(struct mailsem_internal)); + if (sem->sem_sem == NULL) + goto free; + + r = mailsem_internal_init(sem->sem_sem, 0); + if (r < 0) + goto free_sem; + + return sem; + + free_sem: + free(sem->sem_sem); + free: + free(sem); + err: + return NULL; +} + +void mailsem_free(struct mailsem * sem) +{ + mailsem_internal_destroy(sem->sem_sem); + free(sem->sem_sem); + free(sem); +} + +int mailsem_up(struct mailsem * sem) +{ + return mailsem_internal_post(sem->sem_sem); +} + +int mailsem_down(struct mailsem * sem) +{ + return mailsem_internal_wait(sem->sem_sem); +} Added: freeswitch/trunk/libs/libetpan/src/data-types/mailsem.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mailsem.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,51 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsem.h,v 1.2 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAILSEM_H + +#define MAILSEM_H + +struct mailsem { + void * sem_sem; + int sem_kind; +}; + +struct mailsem * mailsem_new(void); +void mailsem_free(struct mailsem * sem); + +int mailsem_up(struct mailsem * sem); +int mailsem_down(struct mailsem * sem); + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/mailstream.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mailstream.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,403 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream.c,v 1.18 2006/06/28 06:13:47 skunk Exp $ + */ + +#include "mailstream.h" +#include "maillock.h" +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> + +#define DEFAULT_NETWORK_TIMEOUT 300 + +#if 0 +#ifdef LIBETPAN_MAILSTREAM_DEBUG + +#define STREAM_DEBUG + +#include <stdio.h> + +#define LOG_FILE "libetpan-stream-debug.log" + +int mailstream_debug = 0; + +#define STREAM_LOG_BUF(buf, size) \ + if (mailstream_debug) { \ + FILE * f; \ + mode_t old_mask; \ + \ + old_mask = umask(0077); \ + f = fopen(LOG_FILE, "a"); \ + umask(old_mask); \ + if (f != NULL) { \ + maillock_write_lock(LOG_FILE, fileno(f)); \ + fwrite((buf), 1, (size), f); \ + maillock_write_unlock(LOG_FILE, fileno(f)); \ + fclose(f); \ + } \ + } + +#define STREAM_LOG(str) \ + if (mailstream_debug) { \ + FILE * f; \ + mode_t old_mask; \ + \ + old_mask = umask(0077); \ + f = fopen(LOG_FILE, "a"); \ + umask(old_mask); \ + if (f != NULL) { \ + maillock_write_lock(LOG_FILE, fileno(f)); \ + fputs((str), f); \ + maillock_write_unlock(LOG_FILE, fileno(f)); \ + fclose(f); \ + } \ + } + +#else + +#define STREAM_LOG_BUF(buf, size) do { } while (0) +#define STREAM_LOG(buf) do { } while (0) + +#endif +#endif + +#define STREAM_LOG_BUF(buf, size) do { } while (0) +#define STREAM_LOG(buf) do { } while (0) + + +mailstream * mailstream_new(mailstream_low * low, size_t buffer_size) +{ + mailstream * s; + + s = malloc(sizeof(* s)); + if (s == NULL) + goto err; + + s->read_buffer = malloc(buffer_size); + if (s->read_buffer == NULL) + goto free_s; + s->read_buffer_len = 0; + + s->write_buffer = malloc(buffer_size); + if (s->write_buffer == NULL) + goto free_read_buffer; + s->write_buffer_len = 0; + + s->buffer_max_size = buffer_size; + s->low = low; + + return s; + + free_read_buffer: + free(s->read_buffer); + free_s: + free(s); + err: + return NULL; +} + +static size_t write_to_internal_buffer(mailstream * s, + const void * buf, size_t count) +{ + memcpy(s->write_buffer + s->write_buffer_len, buf, count); + s->write_buffer_len += count; + + return count; +} + +static size_t write_direct(mailstream * s, const void * buf, size_t count) +{ + size_t left; + const char * cur_buf; + ssize_t written; + + cur_buf = buf; + left = count; + while (left > 0) { + written = mailstream_low_write(s->low, cur_buf, left); + + if (written == -1) { + if (count == left) + return -1; + else + return count - left; + } + + cur_buf += written; + left -= written; + } + + return count; +} + +ssize_t mailstream_write(mailstream * s, const void * buf, size_t count) +{ + int r; + + if (s == NULL) + return -1; + + if (count + s->write_buffer_len > s->buffer_max_size) { + r = mailstream_flush(s); + if (r == -1) + return -1; + + if (count > s->buffer_max_size) + return write_direct(s, buf, count); + } + +#ifdef STREAM_DEBUG + STREAM_LOG(">>>>>>> send >>>>>>\n"); + STREAM_LOG_BUF(buf, count); + STREAM_LOG("\n"); + STREAM_LOG(">>>>>>> end send >>>>>>\n"); +#endif + + return write_to_internal_buffer(s, buf, count); +} + +int mailstream_flush(mailstream * s) +{ + char * cur_buf; + size_t left; + ssize_t written; + + if (s == NULL) + return -1; + + cur_buf = s->write_buffer; + left = s->write_buffer_len; + while (left > 0) { + written = mailstream_low_write(s->low, cur_buf, left); + + if (written == -1) + goto move_buffer; + cur_buf += written; + left -= written; + } + + s->write_buffer_len = 0; + + return 0; + + move_buffer: + memmove(s->write_buffer, cur_buf, left); + s->write_buffer_len = left; + return -1; +} + +static ssize_t read_from_internal_buffer(mailstream * s, + void * buf, size_t count) +{ + if (count >= s->read_buffer_len) + count = s->read_buffer_len; + if (count != 0) + memcpy(buf, s->read_buffer, count); + + s->read_buffer_len -= count; + if (s->read_buffer_len != 0) + memmove(s->read_buffer, s->read_buffer + count, + s->read_buffer_len); + + return count; +} + +static ssize_t read_through_buffer(mailstream * s, void * buf, size_t count) +{ + size_t left; + char * cur_buf; + ssize_t bytes_read; + + cur_buf = buf; + left = count; + + while (left > 0) { + bytes_read = mailstream_low_read(s->low, cur_buf, left); + + if (bytes_read == -1) { + if (count == left) + return -1; + else + return count - left; + } + else if (bytes_read == 0) + return count - left; + + cur_buf += bytes_read; + left -= bytes_read; + } + + return count; +} + +ssize_t mailstream_read(mailstream * s, void * buf, size_t count) +{ + ssize_t read_bytes; + char * cur_buf; + size_t left; + + if (s == NULL) + return -1; + + left = count; + cur_buf = buf; + read_bytes = read_from_internal_buffer(s, cur_buf, left); + cur_buf += read_bytes; + left -= read_bytes; + + if (left == 0) { +#ifdef STREAM_DEBUG + STREAM_LOG("<<<<<<< read <<<<<<\n"); + STREAM_LOG_BUF(buf, read_bytes); + STREAM_LOG("\n"); + STREAM_LOG("<<<<<<< end read <<<<<<\n"); +#endif + + return read_bytes; + } + + if (left > s->buffer_max_size) { + read_bytes = read_through_buffer(s, cur_buf, left); + if (read_bytes == -1) { + if (count == left) + return -1; + else { + +#ifdef STREAM_DEBUG + STREAM_LOG("<<<<<<< read <<<<<<\n"); + STREAM_LOG_BUF(buf, count - left); + STREAM_LOG("\n"); + STREAM_LOG("<<<<<<< end read <<<<<<\n"); +#endif + + return count - left; + } + } + + cur_buf += read_bytes; + left -= read_bytes; + +#ifdef STREAM_DEBUG + STREAM_LOG("<<<<<<< read <<<<<<\n"); + STREAM_LOG_BUF(buf, count - left); + STREAM_LOG("\n"); + STREAM_LOG("<<<<<<< end read <<<<<<\n"); +#endif + + return count - left; + } + + read_bytes = mailstream_low_read(s->low, s->read_buffer, s->buffer_max_size); + if (read_bytes == -1) { + if (left == count) + return -1; + else { +#ifdef STREAM_DEBUG + STREAM_LOG("<<<<<<< read <<<<<<\n"); + STREAM_LOG_BUF(buf, count - left); + STREAM_LOG("\n"); + STREAM_LOG("<<<<<<< end read <<<<<<\n"); +#endif + + return count - left; + } + } + else + s->read_buffer_len += read_bytes; + + read_bytes = read_from_internal_buffer(s, cur_buf, left); + cur_buf += read_bytes; + left -= read_bytes; + +#ifdef STREAM_DEBUG + STREAM_LOG("<<<<<<< read <<<<<<\n"); + STREAM_LOG_BUF(buf, count - left); + STREAM_LOG("\n"); + STREAM_LOG("<<<<<<< end read <<<<<<\n"); +#endif + + return count - left; +} + +mailstream_low * mailstream_get_low(mailstream * s) +{ + return s->low; +} + +void mailstream_set_low(mailstream * s, mailstream_low * low) +{ + s->low = low; +} + +int mailstream_close(mailstream * s) +{ + mailstream_low_close(s->low); + mailstream_low_free(s->low); + + free(s->read_buffer); + free(s->write_buffer); + + free(s); + + return 0; +} + + + +ssize_t mailstream_feed_read_buffer(mailstream * s) +{ + ssize_t read_bytes; + + if (s == NULL) + return -1; + + if (s->read_buffer_len == 0) { + read_bytes = mailstream_low_read(s->low, s->read_buffer, + s->buffer_max_size); + if (read_bytes == -1) + return -1; + s->read_buffer_len += read_bytes; + } + + return s->read_buffer_len; +} + +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L +struct timeval mailstream_network_delay = +{ DEFAULT_NETWORK_TIMEOUT, 0 }; +#else +struct timeval mailstream_network_delay = + { .tv_sec = DEFAULT_NETWORK_TIMEOUT, .tv_usec = 0 }; +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/mailstream.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mailstream.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,81 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream.h,v 1.16 2005/07/15 16:12:33 hoa Exp $ + */ + +#ifndef MAILSTREAM_H + +#define MAILSTREAM_H + +#ifndef _MSC_VER +# include <sys/time.h> +#endif + +#include <libetpan/mailstream_low.h> +#include <libetpan/mailstream_helper.h> +#include <libetpan/mailstream_socket.h> +#include <libetpan/mailstream_ssl.h> +#include <libetpan/mailstream_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +mailstream * mailstream_new(mailstream_low * low, size_t buffer_size); +ssize_t mailstream_write(mailstream * s, const void * buf, size_t count); +ssize_t mailstream_read(mailstream * s, void * buf, size_t count); +int mailstream_close(mailstream * s); +int mailstream_flush(mailstream * s); +ssize_t mailstream_feed_read_buffer(mailstream * s); +mailstream_low * mailstream_get_low(mailstream * s); +void mailstream_set_low(mailstream * s, mailstream_low * low); + +#ifdef LIBETPAN_MAILSTREAM_DEBUG +LIBETPAN_EXPORT +extern int mailstream_debug; + +/* direction is 1 for send, 0 for receive, -1 when it does not apply */ +LIBETPAN_EXPORT +extern void (* mailstream_logger)(int direction, + const char * str, size_t size); +#endif + +#define LIBETPAN_MAILSTREAM_NETWORK_DELAY +extern struct timeval mailstream_network_delay; + +#ifdef __cplusplus +} +#endif + +#endif + Added: freeswitch/trunk/libs/libetpan/src/data-types/mailstream_helper.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mailstream_helper.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,519 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_helper.c,v 1.17 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailstream_helper.h" +#include <string.h> +#include <stdio.h> +#include "mail.h" + +static void remove_trailing_eol(MMAPString * mmapstr) +{ + if (mmapstr->str[mmapstr->len - 1] == '\n') { + mmapstr->len --; + mmapstr->str[mmapstr->len] = '\0'; + } + if (mmapstr->str[mmapstr->len - 1] == '\r') { + mmapstr->len --; + mmapstr->str[mmapstr->len] = '\0'; + } +} + +char * mailstream_read_line(mailstream * stream, MMAPString * line) +{ + if (mmap_string_assign(line, "") == NULL) + return NULL; + + return mailstream_read_line_append(stream, line); +} + +static char * mailstream_read_len_append(mailstream * stream, + MMAPString * line, + size_t i) +{ + size_t cur_size; + + cur_size = line->len; + if (mmap_string_set_size(line, line->len + i) == NULL) + return NULL; + if (mailstream_read(stream, line->str + cur_size, i) < 0) + return NULL; + return line->str; +} + +char * mailstream_read_line_append(mailstream * stream, MMAPString * line) +{ + if (stream == NULL) + return NULL; + + do { + if (stream->read_buffer_len > 0) { + size_t i; + + i = 0; + while (i < stream->read_buffer_len) { + if (stream->read_buffer[i] == '\n') + return mailstream_read_len_append(stream, line, i + 1); + i++; + } + if (mailstream_read_len_append(stream, line, + stream->read_buffer_len) == NULL) + return NULL; + } + else { + ssize_t r; + + r = mailstream_feed_read_buffer(stream); + if (r == -1) + return NULL; + + if (r == 0) + break; + } + } + while (1); + + return line->str; +} + +char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line) +{ + if (!mailstream_read_line(stream, line)) + return NULL; + + remove_trailing_eol(line); + + return line->str; +} + +int mailstream_is_end_multiline(const char * line) +{ + if (line[0] != '.') + return FALSE; + if (line[1] != 0) + return FALSE; + return TRUE; +} + +#if 1 +char * mailstream_read_multiline(mailstream * s, size_t size, + MMAPString * stream_buffer, + MMAPString * multiline_buffer, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t count; + char * line; + size_t last; + + if (mmap_string_assign(multiline_buffer, "") == NULL) + return NULL; + + count = 0; + last = 0; + + while ((line = mailstream_read_line_remove_eol(s, stream_buffer)) != NULL) { + if (mailstream_is_end_multiline(line)) + return multiline_buffer->str; + + if (line[0] == '.') { + if (mmap_string_append(multiline_buffer, line + 1) == NULL) + return NULL; + } + else { + if (mmap_string_append(multiline_buffer, line) == NULL) + return NULL; + } + if (mmap_string_append(multiline_buffer, "\r\n") == NULL) + return NULL; + + count += strlen(line); + if ((size != 0) && (progr_rate != 0) && (progr_fun != NULL)) + if (count - last >= progr_rate) { + (* progr_fun)(count, size); + last = count; + } + } + + return NULL; +} + +#else + +/* + high speed but don't replace the line break with '\n' and neither + remove the '.' +*/ + +static gboolean end_of_multiline(const char * str, gint len) +{ + gint index; + + index = len - 1; + + if (str[index] != '\n') + return FALSE; + if (index == 0) + return FALSE; + + index --; + + if (str[index] == '\r') { + index --; + if (index == 0) + return FALSE; + } + + if (str[index] != '.') + return FALSE; + if (index == 0) + return FALSE; + + index--; + + if (str[index] != '\n') + return FALSE; + + return TRUE; +} + +char * mailstream_read_multiline(mailstream * stream, size_t size, + MMAPString * stream_buffer, + MMAPString * line, + size_t progr_rate, + progress_function * progr_fun) +{ + if (stream == NULL) + return NULL; + + mmap_string_assign(line, ""); + + do { + if (stream->read_buffer_len > 0) { + size_t i; + + i = 0; + while (i < stream->read_buffer_len) { + if (end_of_multiline(stream->read_buffer, i + 1)) + return mailstream_read_len_append(stream, line, i + 1); + i++; + } + if (mailstream_read_len_append(stream, line, + stream->read_buffer_len) == NULL) + return NULL; + if (end_of_multiline(line->str, line->len)) + return line->str; + } + else + if (mailstream_feed_read_buffer(stream) == -1) + return NULL; + } + while (1); + + return line->str; +} +#endif + + + +static inline ssize_t send_data_line(mailstream * s, + const char * line, size_t length) +{ + int fix_eol; + const char * start; + size_t count; + + start = line; + + fix_eol = 0; + count = 0; + + while (1) { + if (length == 0) + break; + + if (* line == '\r') { + line ++; + + count ++; + length --; + + if (length == 0) { + fix_eol = 1; + break; + } + + if (* line == '\n') { + line ++; + + count ++; + length --; + + break; + } + else { + fix_eol = 1; + break; + } + } + else if (* line == '\n') { + line ++; + + count ++; + length --; + + fix_eol = 1; + break; + } + + line ++; + length --; + count ++; + } + + if (fix_eol) { + if (mailstream_write(s, start, count - 1) == -1) + goto err; + if (mailstream_write(s, "\r\n", 2) == -1) + goto err; + } + else { + if (mailstream_write(s, start, count) == -1) + goto err; + } + + +#if 0 + while (* line != '\n') { + if (* line == '\r') + pos = line; + if (* line == '\0') + return line; + if (mailstream_write(s, line, 1) == -1) + goto err; + line ++; + } + if (pos + 1 == line) { + if (mailstream_write(s, line, 1) == -1) + goto err; + } + else { + if (mailstream_write(s, "\r\n", 2) == -1) + goto err; + } + line ++; +#endif + + return count; + + err: + return -1; +} + +static inline int send_data_crlf(mailstream * s, const char * message, + size_t size, + int quoted, + size_t progr_rate, + progress_function * progr_fun) +{ + const char * current; + size_t count; + size_t last; + size_t remaining; + + count = 0; + last = 0; + + current = message; + remaining = size; + + while (remaining > 0) { + ssize_t length; + + if (quoted) { + if (current[0] == '.') + if (mailstream_write(s, ".", 1) == -1) + goto err; + } + + length = send_data_line(s, current, remaining); + if (length < 0) + goto err; + + current += length; + + count += length; + if ((progr_rate != 0) && (progr_fun != NULL)) + if (count - last >= progr_rate) { + (* progr_fun)(count, size); + last = count; + } + + remaining -= length; + } + + return 0; + + err: + return -1; +} + +int mailstream_send_data_crlf(mailstream * s, const char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun) +{ + return send_data_crlf(s, message, size, 0, progr_rate, progr_fun); +} + +int mailstream_send_data(mailstream * s, const char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun) +{ + if (send_data_crlf(s, message, size, 1, progr_rate, progr_fun) == -1) + goto err; + + if (mailstream_write(s, "\r\n.\r\n", 5) == -1) + goto err; + + if (mailstream_flush(s) == -1) + goto err; + + return 0; + + err: + return -1; +} + +static inline ssize_t get_data_size(const char * line, size_t length, + size_t * result) +{ + int fix_eol; + const char * start; + size_t count; + size_t fixed_count; + + start = line; + + fix_eol = 0; + count = 0; + fixed_count = 0; + + while (1) { + if (length == 0) + break; + + if (* line == '\r') { + line ++; + + count ++; + length --; + + if (length == 0) { + fix_eol = 1; + fixed_count ++; + break; + } + + if (* line == '\n') { + line ++; + + count ++; + length --; + + break; + } + else { + fix_eol = 1; + fixed_count ++; + break; + } + } + else if (* line == '\n') { + line ++; + + count ++; + length --; + + fix_eol = 1; + fixed_count ++; + break; + } + + line ++; + length --; + count ++; + } + + * result = count + fixed_count; + + return count; +} + +size_t mailstream_get_data_crlf_size(const char * message, size_t size) +{ + const char * current; + size_t count; + size_t last; + size_t remaining; + size_t fixed_count; + + count = 0; + last = 0; + fixed_count = 0; + + current = message; + remaining = size; + + while (remaining > 0) { + ssize_t length; + size_t line_count; + + length = get_data_size(current, remaining, &line_count); + + fixed_count += line_count; + current += length; + + count += length; + + remaining -= length; + } + + return fixed_count; +} Added: freeswitch/trunk/libs/libetpan/src/data-types/mailstream_helper.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mailstream_helper.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,77 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_helper.h,v 1.12 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAILSTREAM_HELPER_H + +#define MAILSTREAM_HELPER_H + +#include <libetpan/mmapstring.h> +#include <libetpan/mailstream.h> + +#ifdef __cplusplus +extern "C" { +#endif + +char * mailstream_read_line(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_append(mailstream * stream, MMAPString * line); + +char * mailstream_read_line_remove_eol(mailstream * stream, MMAPString * line); + +char * mailstream_read_multiline(mailstream * s, size_t size, + MMAPString * stream_buffer, + MMAPString * multiline_buffer, + size_t progr_rate, + progress_function * progr_fun); + +int mailstream_is_end_multiline(const char * line); + +int mailstream_send_data_crlf(mailstream * s, const char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun); + +int mailstream_send_data(mailstream * s, const char * message, + size_t size, + size_t progr_rate, + progress_function * progr_fun); + +size_t mailstream_get_data_crlf_size(const char * message, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/mailstream_low.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mailstream_low.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,186 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_low.c,v 1.17 2006/05/22 13:39:40 hoa Exp $ + */ + +#include "mailstream_low.h" +#include <stdlib.h> + +#ifdef LIBETPAN_MAILSTREAM_DEBUG + +#define STREAM_DEBUG + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include "maillock.h" +#ifdef _MSC_VER +# include "win_etpan.h" +#endif + +#define LOG_FILE "libetpan-stream-debug.log" + +LIBETPAN_EXPORT +int mailstream_debug = 0; + +LIBETPAN_EXPORT +void (* mailstream_logger)(int direction, + const char * str, size_t size) = NULL; + +#define STREAM_LOG_BUF(direction, buf, size) \ + if (mailstream_debug) { \ + if (mailstream_logger != NULL) { \ + mailstream_logger(direction, buf, size); \ + } \ + else { \ + FILE * f; \ + mode_t old_mask; \ + \ + old_mask = umask(0077); \ + f = fopen(LOG_FILE, "a"); \ + umask(old_mask); \ + if (f != NULL) { \ + maillock_write_lock(LOG_FILE, fileno(f)); \ + fwrite((buf), 1, (size), f); \ + maillock_write_unlock(LOG_FILE, fileno(f)); \ + fclose(f); \ + } \ + } \ + } + +#define STREAM_LOG(direction, str) \ + if (mailstream_debug) { \ + if (mailstream_logger != NULL) { \ + mailstream_logger(direction, str, strlen(str) + 1); \ + } \ + else { \ + FILE * f; \ + mode_t old_mask; \ + \ + old_mask = umask(0077); \ + f = fopen(LOG_FILE, "a"); \ + umask(old_mask); \ + if (f != NULL) { \ + maillock_write_lock(LOG_FILE, fileno(f)); \ + fputs((str), f); \ + maillock_write_unlock(LOG_FILE, fileno(f)); \ + fclose(f); \ + } \ + } \ + } + +#else + +#define STREAM_LOG_BUF(direction, buf, size) do { } while (0) +#define STREAM_LOG(direction, buf) do { } while (0) + +#endif + + +/* general functions */ + +mailstream_low * mailstream_low_new(void * data, + mailstream_low_driver * driver) +{ + mailstream_low * s; + + s = malloc(sizeof(* s)); + if (s == NULL) + return NULL; + + s->data = data; + s->driver = driver; + + return s; +} + +int mailstream_low_close(mailstream_low * s) +{ + if (s == NULL) + return -1; + s->driver->mailstream_close(s); + + return 0; +} + +int mailstream_low_get_fd(mailstream_low * s) +{ + if (s == NULL) + return -1; + return s->driver->mailstream_get_fd(s); +} + +void mailstream_low_free(mailstream_low * s) +{ + s->driver->mailstream_free(s); +} + +ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count) +{ + ssize_t r; + + if (s == NULL) + return -1; + r = s->driver->mailstream_read(s, buf, count); + +#ifdef STREAM_DEBUG + if (r > 0) { + STREAM_LOG(0, "<<<<<<< read <<<<<<\n"); + STREAM_LOG_BUF(0, buf, r); + STREAM_LOG(0, "\n"); + STREAM_LOG(0, "<<<<<<< end read <<<<<<\n"); + } +#endif + + return r; +} + +ssize_t mailstream_low_write(mailstream_low * s, + const void * buf, size_t count) +{ + if (s == NULL) + return -1; + +#ifdef STREAM_DEBUG + STREAM_LOG(1, ">>>>>>> send >>>>>>\n"); + STREAM_LOG_BUF(1, buf, count); + STREAM_LOG(1, "\n"); + STREAM_LOG(1, ">>>>>>> end send >>>>>>\n"); +#endif + + return s->driver->mailstream_write(s, buf, count); +} Added: freeswitch/trunk/libs/libetpan/src/data-types/mailstream_low.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mailstream_low.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_low.h,v 1.9 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAILSTREAM_LOW_H + +#define MAILSTREAM_LOW_H + +#include <sys/types.h> +#include <libetpan/mailstream_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* general functions */ + +mailstream_low * mailstream_low_new(void * data, + mailstream_low_driver * driver); +ssize_t mailstream_low_write(mailstream_low * s, + const void * buf, size_t count); +ssize_t mailstream_low_read(mailstream_low * s, void * buf, size_t count); +int mailstream_low_close(mailstream_low * s); +int mailstream_low_get_fd(mailstream_low * s); +void mailstream_low_free(mailstream_low * s); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/mailstream_socket.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mailstream_socket.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,279 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_socket.c,v 1.22 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailstream_socket.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <stdlib.h> +#include <fcntl.h> +#ifdef HAVE_SYS_SOCKET_H +# include <sys/socket.h> +#endif + +#ifdef HAVE_STRING_H +# include <string.h> +#endif + +/* + these 3 headers MUST be included before <sys/select.h> + to insure compatibility with Mac OS X (this is true for 10.2) +*/ + +#ifndef _MSC_VER +# include <sys/time.h> +# include <sys/types.h> +# ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +# endif +#endif + +/* mailstream_low, socket */ + +static int mailstream_low_socket_close(mailstream_low * s); +static ssize_t mailstream_low_socket_read(mailstream_low * s, + void * buf, size_t count); +static ssize_t mailstream_low_socket_write(mailstream_low * s, + const void * buf, size_t count); +static void mailstream_low_socket_free(mailstream_low * s); +static int mailstream_low_socket_get_fd(mailstream_low * s); + +static mailstream_low_driver local_mailstream_socket_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* SEB */ + mailstream_low_socket_read, + mailstream_low_socket_write, + mailstream_low_socket_close, + mailstream_low_socket_get_fd, + mailstream_low_socket_free +#else + mailstream_read: mailstream_low_socket_read, + mailstream_write: mailstream_low_socket_write, + mailstream_close: mailstream_low_socket_close, + mailstream_free: mailstream_low_socket_free, + mailstream_get_fd: mailstream_low_socket_get_fd, +#endif +}; + +mailstream_low_driver * mailstream_socket_driver = +&local_mailstream_socket_driver; + +/* file descriptor must be given in (default) blocking-mode */ + +static struct mailstream_socket_data * socket_data_new(int fd) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data * ) malloc(sizeof(* socket_data)); + if (socket_data == NULL) + goto err; + + socket_data->fd = fd; + + return socket_data; + + err: + return NULL; +} + +static void socket_data_free(struct mailstream_socket_data * socket_data) +{ + free(socket_data); +} + +static void socket_data_close(struct mailstream_socket_data * socket_data) +{ +#ifdef _MSC_VER +/* SEB */ + closesocket(socket_data->fd); +#else + close(socket_data->fd); +#endif + socket_data->fd = -1; +} + +mailstream_low * mailstream_low_socket_open(int fd) +{ + mailstream_low * s; + struct mailstream_socket_data * socket_data; + + socket_data = socket_data_new(fd); + if (socket_data == NULL) + goto err; + + s = mailstream_low_new(socket_data, mailstream_socket_driver); + if (s == NULL) + goto free_socket_data; + + return s; + + free_socket_data: + socket_data_free(socket_data); + err: + return NULL; +} + +static int mailstream_low_socket_close(mailstream_low * s) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + socket_data_close(socket_data); + + return 0; +} + +static void mailstream_low_socket_free(mailstream_low * s) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + socket_data_free(socket_data); + s->data = NULL; + + free(s); +} + +static int mailstream_low_socket_get_fd(mailstream_low * s) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + return socket_data->fd; +} + + +static ssize_t mailstream_low_socket_read(mailstream_low * s, + void * buf, size_t count) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + + /* timeout */ + { + fd_set fds_read; + fd_set fds_excp; + struct timeval timeout; + int r; + + timeout = mailstream_network_delay; + + FD_ZERO(&fds_read); + FD_SET(socket_data->fd, &fds_read); + FD_ZERO(&fds_excp); + FD_SET(socket_data->fd, &fds_excp); + r = select(socket_data->fd + 1, &fds_read, NULL, &fds_excp, &timeout); + if (r == 0) + return -1; + if (FD_ISSET(socket_data->fd, &fds_excp)) + return -1; + if (!FD_ISSET(socket_data->fd, &fds_read)) + return 0; + } + +/* SEB why not for all os ? */ +#ifdef WIN32 + return recv(socket_data->fd, buf, count, 0); +#else + return read(socket_data->fd, buf, count); +#endif +} + +static ssize_t mailstream_low_socket_write(mailstream_low * s, + const void * buf, size_t count) +{ + struct mailstream_socket_data * socket_data; + + socket_data = (struct mailstream_socket_data *) s->data; + /* timeout */ + { + fd_set fds_write; + fd_set fds_excp; + struct timeval timeout; + int r; + + timeout = mailstream_network_delay; + + FD_ZERO(&fds_write); + FD_SET(socket_data->fd, &fds_write); + FD_ZERO(&fds_excp); + FD_SET(socket_data->fd, &fds_excp); + r = select(socket_data->fd + 1, NULL, &fds_write, &fds_excp, &timeout); + if (r == 0) + return -1; + if (FD_ISSET(socket_data->fd, &fds_excp)) + return -1; + if (!FD_ISSET(socket_data->fd, &fds_write)) + return 0; + } + +/* SEB (bis) why not for all os? */ +#ifdef WIN32 + return send(socket_data->fd, buf, count, 0); +#else + return write(socket_data->fd, buf, count); +#endif +} + + +/* mailstream */ + +mailstream * mailstream_socket_open(int fd) +{ + mailstream_low * low; + mailstream * s; + + low = mailstream_low_socket_open(fd); + if (low == NULL) + goto err; + + s = mailstream_new(low, 8192); + if (s == NULL) + goto free_low; + + return s; + + free_low: + mailstream_low_close(low); + err: + return NULL; +} + Added: freeswitch/trunk/libs/libetpan/src/data-types/mailstream_socket.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mailstream_socket.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,61 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_socket.h,v 1.9 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAILSTREAM_SOCKET_H + +#define MAILSTREAM_SOCKET_H + +#include <libetpan/mailstream.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* socket */ + +extern mailstream_low_driver * mailstream_socket_driver; + +mailstream_low * mailstream_low_socket_open(int fd); +mailstream * mailstream_socket_open(int fd); + +struct mailstream_socket_data { + int fd; +}; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/mailstream_ssl.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mailstream_ssl.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,701 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_ssl.c,v 1.41 2006/09/25 17:33:03 colinleroy Exp $ + */ + +/* + NOTE : + + The user has to call himself SSL_library_init() if he wants to + use SSL. +*/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailstream_ssl.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef HAVE_STDLIB_H +# include <stdlib.h> +#endif +#include <fcntl.h> + +/* + these 3 headers MUST be included before <sys/select.h> + to insure compatibility with Mac OS X (this is true for 10.2) +*/ +#ifndef _MSC_VER +# include <sys/time.h> +# include <sys/types.h> +# ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +# endif +#endif + +/* mailstream_low, ssl */ + +#ifdef USE_SSL +# ifndef USE_GNUTLS +# include <openssl/ssl.h> +# else +# include <errno.h> +# include <gnutls/gnutls.h> +# include <gnutls/x509.h> +# endif +# ifdef LIBETPAN_REENTRANT +# include <pthread.h> +# endif +#endif + +#ifdef USE_SSL +#ifndef USE_GNUTLS +struct mailstream_ssl_data { + int fd; + SSL * ssl_conn; + SSL_CTX * ssl_ctx; +}; +#else +struct mailstream_ssl_data { + int fd; + gnutls_session session; +}; +#endif +#endif + +#ifdef USE_SSL +#ifdef LIBETPAN_REENTRANT +static pthread_mutex_t ssl_lock = PTHREAD_MUTEX_INITIALIZER; +#endif +static int gnutls_init_done = 0; +static int openssl_init_done = 0; +#endif + +void mailstream_gnutls_init_not_required(void) +{ +#ifdef USE_SSL +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&ssl_lock); +#endif + gnutls_init_done = 1; +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&ssl_lock); +#endif +#endif +} + +void mailstream_openssl_init_not_required(void) +{ +#ifdef USE_SSL +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&ssl_lock); +#endif + openssl_init_done = 1; +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&ssl_lock); +#endif +#endif +} + +void mailstream_ssl_init_not_required(void) +{ + mailstream_gnutls_init_not_required(); + mailstream_openssl_init_not_required(); +} + +static inline void mailstream_ssl_init(void) +{ +#ifdef USE_SSL +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&ssl_lock); +#endif +#ifndef USE_GNUTLS + if (!openssl_init_done) { + SSL_library_init(); + openssl_init_done = 1; + } +#else + if (!gnutls_init_done) { + gnutls_global_init(); + gnutls_init_done = 1; + } +#endif +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&ssl_lock); +#endif +#endif +} + +#ifdef USE_SSL +static inline int mailstream_prepare_fd(int fd) +{ +#ifndef WIN32 + int fd_flags; + int r; + + fd_flags = fcntl(fd, F_GETFL, 0); + fd_flags |= O_NDELAY; + r = fcntl(fd, F_SETFL, fd_flags); + if (r < 0) + return -1; +#endif + + return 0; +} +#endif + + +#ifdef USE_SSL +static int mailstream_low_ssl_close(mailstream_low * s); +static ssize_t mailstream_low_ssl_read(mailstream_low * s, + void * buf, size_t count); +static ssize_t mailstream_low_ssl_write(mailstream_low * s, + const void * buf, size_t count); +static void mailstream_low_ssl_free(mailstream_low * s); +static int mailstream_low_ssl_get_fd(mailstream_low * s); + +#if defined (_MSC_VER) || defined (__SUNPRO_CC) || defined (__SUNPRO_C) +static mailstream_low_driver local_mailstream_ssl_driver = { + /* mailstream_read */ mailstream_low_ssl_read, + /* mailstream_write */ mailstream_low_ssl_write, + /* mailstream_close */ mailstream_low_ssl_close, + /* mailstream_free */ mailstream_low_ssl_free, + /* mailstream_get_fd */ mailstream_low_ssl_get_fd, +#else +static mailstream_low_driver local_mailstream_ssl_driver = { + mailstream_read: mailstream_low_ssl_read, + mailstream_write: mailstream_low_ssl_write, + mailstream_close: mailstream_low_ssl_close, + mailstream_free: mailstream_low_ssl_free, + mailstream_get_fd: mailstream_low_ssl_get_fd, +#endif +}; + +mailstream_low_driver * mailstream_ssl_driver = &local_mailstream_ssl_driver; +#endif + +/* file descriptor must be given in (default) blocking-mode */ + +#ifdef USE_SSL +#ifndef USE_GNUTLS +static struct mailstream_ssl_data * ssl_data_new_full(int fd, SSL_METHOD *method) +{ + struct mailstream_ssl_data * ssl_data; + SSL * ssl_conn; + int r; + SSL_CTX * tmp_ctx; + + mailstream_ssl_init(); + + tmp_ctx = SSL_CTX_new(method); + if (tmp_ctx == NULL) + goto err; + + ssl_conn = (SSL *) SSL_new(tmp_ctx); + if (ssl_conn == NULL) + goto free_ctx; + + if (SSL_set_fd(ssl_conn, fd) == 0) + goto free_ssl_conn; + + r = SSL_connect(ssl_conn); + if (r <= 0) + goto free_ssl_conn; + + r = mailstream_prepare_fd(fd); + if (r < 0) + goto free_ssl_conn; + + ssl_data = malloc(sizeof(* ssl_data)); + if (ssl_data == NULL) + goto free_ctx; + + ssl_data->fd = fd; + ssl_data->ssl_conn = ssl_conn; + ssl_data->ssl_ctx = tmp_ctx; + + return ssl_data; + + free_ctx: + SSL_CTX_free(tmp_ctx); + free_ssl_conn: + SSL_free(ssl_conn); + err: + return NULL; +} +static struct mailstream_ssl_data * ssl_data_new(int fd) +{ + return ssl_data_new_full(fd, SSLv23_client_method()); +} + +static struct mailstream_ssl_data * tls_data_new(int fd) +{ + return ssl_data_new_full(fd, TLSv1_client_method()); +} + +#else +static struct mailstream_ssl_data * ssl_data_new(int fd) +{ + struct mailstream_ssl_data * ssl_data; + gnutls_session session; + + const int cipher_prio[] = { GNUTLS_CIPHER_AES_128_CBC, + GNUTLS_CIPHER_3DES_CBC, + GNUTLS_CIPHER_AES_256_CBC, + GNUTLS_CIPHER_ARCFOUR_128, 0 }; + const int kx_prio[] = { GNUTLS_KX_DHE_RSA, + GNUTLS_KX_RSA, + GNUTLS_KX_DHE_DSS, 0 }; + const int mac_prio[] = { GNUTLS_MAC_SHA1, + GNUTLS_MAC_MD5, 0 }; + const int proto_prio[] = { GNUTLS_TLS1, + GNUTLS_SSL3, 0 }; + + gnutls_certificate_credentials_t xcred; + int r; + + mailstream_ssl_init(); + + if (gnutls_certificate_allocate_credentials (&xcred) != 0) + return NULL; + + r = gnutls_init(&session, GNUTLS_CLIENT); + if (session == NULL || r != 0) + return NULL; + + gnutls_set_default_priority(session); + gnutls_protocol_set_priority (session, proto_prio); + gnutls_cipher_set_priority (session, cipher_prio); + gnutls_kx_set_priority (session, kx_prio); + gnutls_mac_set_priority (session, mac_prio); + + gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred); + + gnutls_transport_set_ptr(session, (gnutls_transport_ptr) fd); + + do { + r = gnutls_handshake(session); + } while (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED); + + if (r < 0) { + goto free_ssl_conn; + } + + r = mailstream_prepare_fd(fd); + if (r < 0) + goto free_ssl_conn; + + ssl_data = malloc(sizeof(* ssl_data)); + if (ssl_data == NULL) + goto err; + + ssl_data->fd = fd; + ssl_data->session = session; + + return ssl_data; + + free_ssl_conn: + gnutls_deinit(session); + err: + return NULL; +} +static struct mailstream_ssl_data * tls_data_new(int fd) +{ + return ssl_data_new(fd); +} +#endif + +static void ssl_data_free(struct mailstream_ssl_data * ssl_data) +{ + free(ssl_data); +} + +#ifndef USE_GNUTLS +static void ssl_data_close(struct mailstream_ssl_data * ssl_data) +{ + SSL_free(ssl_data->ssl_conn); + ssl_data->ssl_conn = NULL; + SSL_CTX_free(ssl_data->ssl_ctx); + ssl_data->ssl_ctx = NULL; + close(ssl_data->fd); + ssl_data->fd = -1; +} +#else +static void ssl_data_close(struct mailstream_ssl_data * ssl_data) +{ + gnutls_deinit(ssl_data->session); + ssl_data->session = NULL; + close(ssl_data->fd); + ssl_data->fd = -1; +} +#endif + +#endif + +mailstream_low * mailstream_low_ssl_open_full(int fd, int starttls) +{ +#ifdef USE_SSL + mailstream_low * s; + struct mailstream_ssl_data * ssl_data; + + if (starttls) + ssl_data = tls_data_new(fd); + else + ssl_data = ssl_data_new(fd); + + if (ssl_data == NULL) + goto err; + + s = mailstream_low_new(ssl_data, mailstream_ssl_driver); + if (s == NULL) + goto free_ssl_data; + + return s; + + free_ssl_data: + ssl_data_free(ssl_data); + err: + return NULL; +#else + return NULL; +#endif +} + +mailstream_low * mailstream_low_ssl_open(int fd) +{ + return mailstream_low_ssl_open_full(fd, 0); +} + +mailstream_low * mailstream_low_tls_open(int fd) +{ + return mailstream_low_ssl_open_full(fd, 1); +} + +#ifdef USE_SSL +static int mailstream_low_ssl_close(mailstream_low * s) +{ + struct mailstream_ssl_data * ssl_data; + + ssl_data = (struct mailstream_ssl_data *) s->data; + ssl_data_close(ssl_data); + + return 0; +} + +static void mailstream_low_ssl_free(mailstream_low * s) +{ + struct mailstream_ssl_data * ssl_data; + + ssl_data = (struct mailstream_ssl_data *) s->data; + ssl_data_free(ssl_data); + s->data = NULL; + + free(s); +} + +static int mailstream_low_ssl_get_fd(mailstream_low * s) +{ + struct mailstream_ssl_data * ssl_data; + + ssl_data = (struct mailstream_ssl_data *) s->data; + return ssl_data->fd; +} + +#ifndef USE_GNUTLS +static ssize_t mailstream_low_ssl_read(mailstream_low * s, + void * buf, size_t count) +{ + struct mailstream_ssl_data * ssl_data; + int r; + + ssl_data = (struct mailstream_ssl_data *) s->data; + + while (1) { + int ssl_r; + fd_set fds_read; + struct timeval timeout; + + r = SSL_read(ssl_data->ssl_conn, buf, count); + if (r > 0) + return r; + + ssl_r = SSL_get_error(ssl_data->ssl_conn, r); + switch (ssl_r) { + case SSL_ERROR_NONE: + return r; + + case SSL_ERROR_ZERO_RETURN: + return r; + + case SSL_ERROR_WANT_READ: + timeout = mailstream_network_delay; + + FD_ZERO(&fds_read); + FD_SET(ssl_data->fd, &fds_read); + r = select(ssl_data->fd + 1, &fds_read, NULL, NULL, &timeout); + if (r == 0) + return -1; + break; + + default: + return -1; + } + } +} +#else +static ssize_t mailstream_low_ssl_read(mailstream_low * s, + void * buf, size_t count) +{ + struct mailstream_ssl_data * ssl_data; + int r; + + ssl_data = (struct mailstream_ssl_data *) s->data; + + while (1) { + int ssl_r; + fd_set fds_read; + struct timeval timeout; + + r = gnutls_record_recv(ssl_data->session, buf, count); + if (r > 0) + return r; + + switch (r) { + case 0: /* closed connection */ + return -1; + + case GNUTLS_E_AGAIN: + case GNUTLS_E_INTERRUPTED: + timeout = mailstream_network_delay; + + FD_ZERO(&fds_read); + FD_SET(ssl_data->fd, &fds_read); + r = select(ssl_data->fd + 1, &fds_read, NULL, NULL, &timeout); + if (r == 0) + return -1; + break; + + default: + return -1; + } + } +} +#endif + +#ifndef USE_GNUTLS +static ssize_t mailstream_low_ssl_write(mailstream_low * s, + const void * buf, size_t count) +{ + struct mailstream_ssl_data * ssl_data; + int ssl_r; + fd_set fds_write; + fd_set fds_excp; + struct timeval timeout; + int r; + + ssl_data = (struct mailstream_ssl_data *) s->data; + + timeout = mailstream_network_delay; + + FD_ZERO(&fds_write); + FD_SET(ssl_data->fd, &fds_write); + FD_ZERO(&fds_excp); + FD_SET(ssl_data->fd, &fds_excp); + + r = select(ssl_data->fd + 1, NULL, &fds_write, &fds_excp, &timeout); + if (r == 0) + return -1; + + if (FD_ISSET(ssl_data->fd, &fds_excp)) + return -1; + + if (!FD_ISSET(ssl_data->fd, &fds_write)) + return 0; + + r = SSL_write(ssl_data->ssl_conn, buf, count); + if (r > 0) + return r; + + ssl_r = SSL_get_error(ssl_data->ssl_conn, r); + switch (ssl_r) { + case SSL_ERROR_NONE: + return r; + + case SSL_ERROR_ZERO_RETURN: + return -1; + + case SSL_ERROR_WANT_WRITE: + return 0; + + default: + return r; + } +} +#else +static ssize_t mailstream_low_ssl_write(mailstream_low * s, + const void * buf, size_t count) +{ + struct mailstream_ssl_data * ssl_data; + int ssl_r; + fd_set fds_write; + fd_set fds_excp; + struct timeval timeout; + int r; + + ssl_data = (struct mailstream_ssl_data *) s->data; + + timeout = mailstream_network_delay; + + FD_ZERO(&fds_write); + FD_SET(ssl_data->fd, &fds_write); + FD_ZERO(&fds_excp); + FD_SET(ssl_data->fd, &fds_excp); + + r = select(ssl_data->fd + 1, NULL, &fds_write, &fds_excp, &timeout); + if (r == 0) + return -1; + + if (FD_ISSET(ssl_data->fd, &fds_excp)) + return -1; + + if (!FD_ISSET(ssl_data->fd, &fds_write)) + return 0; + + r = gnutls_record_send(ssl_data->session, buf, count); + if (r > 0) + return r; + + switch (r) { + case 0: + return -1; + + case GNUTLS_E_AGAIN: + case GNUTLS_E_INTERRUPTED: + return 0; + + default: + return r; + } +} +#endif +#endif + +/* mailstream */ + +mailstream * mailstream_ssl_open(int fd) +{ +#ifdef USE_SSL + mailstream_low * low; + mailstream * s; + + low = mailstream_low_ssl_open(fd); + if (low == NULL) + goto err; + + s = mailstream_new(low, 8192); + if (s == NULL) + goto free_low; + + return s; + + free_low: + mailstream_low_close(low); + err: + return NULL; +#else + return NULL; +#endif +} + +int mailstream_ssl_get_certificate(mailstream *stream, unsigned char **cert_DER) +{ +#ifdef USE_SSL + struct mailstream_ssl_data *data = NULL; + int len = 0; +#ifndef USE_GNUTLS + SSL *ssl_conn = NULL; + X509 *cert = NULL; +#else + gnutls_session session = NULL; + const gnutls_datum *raw_cert_list; + unsigned int raw_cert_list_length; + char *exported_cert = NULL; + gnutls_x509_crt cert = NULL; + char output[10*1024]; +#endif + + if (cert_DER == NULL || stream == NULL || stream->low == NULL) + return -1; + + data = stream->low->data; + + if (data == NULL) + return -1; + +#ifndef USE_GNUTLS + ssl_conn = data->ssl_conn; + if (ssl_conn == NULL) + return -1; + cert = SSL_get_peer_certificate(ssl_conn); + if (cert == NULL) + return -1; + *cert_DER = NULL; + len = i2d_X509(cert, cert_DER); + return len; +#else + session = data->session; + raw_cert_list = gnutls_certificate_get_peers(session, &raw_cert_list_length); + + if (raw_cert_list + && gnutls_certificate_type_get(session) == GNUTLS_CRT_X509 + && gnutls_x509_crt_init(&cert) >= 0 + && gnutls_x509_crt_import(cert, &raw_cert_list[0], GNUTLS_X509_FMT_DER) >= 0) { + len = 10*1024; + if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, output, &len) < 0) + return -1; + if (len >= 0) { + *cert_DER = malloc (len + 1); + if (*cert_DER == NULL) + return -1; + memcpy (*cert_DER, output, len); + } + gnutls_x509_crt_deinit(cert); + return len; + } +#endif +#endif + return -1; +} Added: freeswitch/trunk/libs/libetpan/src/data-types/mailstream_ssl.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mailstream_ssl.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,65 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_ssl.h,v 1.12 2006/02/17 20:45:14 colinleroy Exp $ + */ + +#ifndef MAILSTREAM_SSL_H + +#define MAILSTREAM_SSL_H + +#include <libetpan/mailstream.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* socket */ + +#ifdef USE_SSL +extern mailstream_low_driver * mailstream_ssl_driver; +#endif + +mailstream_low * mailstream_low_ssl_open(int fd); +mailstream_low * mailstream_low_tls_open(int fd); +mailstream * mailstream_ssl_open(int fd); + +void mailstream_gnutls_init_not_required(void); +void mailstream_openssl_init_not_required(void); +void mailstream_ssl_init_not_required(void); +int mailstream_ssl_get_certificate(mailstream *stream, unsigned char **cert_DER); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/mailstream_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mailstream_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,90 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstream_types.h,v 1.13 2006/03/22 08:10:47 hoa Exp $ + */ + +#ifndef MAILSTREAM_TYPES_H + +#define MAILSTREAM_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBETPAN_MAILSTREAM_DEBUG +#ifndef LIBETPAN_CONFIG_H +# include <libetpan/libetpan-config.h> +#endif + +struct _mailstream; + +typedef struct _mailstream mailstream; + +struct _mailstream_low; + +typedef struct _mailstream_low mailstream_low; + +struct _mailstream { + size_t buffer_max_size; + + char * write_buffer; + size_t write_buffer_len; + + char * read_buffer; + size_t read_buffer_len; + + mailstream_low * low; +}; + +struct mailstream_low_driver { + ssize_t (* mailstream_read)(mailstream_low *, void *, size_t); + ssize_t (* mailstream_write)(mailstream_low *, const void *, size_t); + int (* mailstream_close)(mailstream_low *); + int (* mailstream_get_fd)(mailstream_low *); + void (* mailstream_free)(mailstream_low *); +}; + +typedef struct mailstream_low_driver mailstream_low_driver; + +struct _mailstream_low { + void * data; + mailstream_low_driver * driver; +}; + +typedef void progress_function(size_t current, size_t maximum); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/mapping.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mapping.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,67 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mapping.c,v 1.7 2006/06/26 11:50:26 hoa Exp $ + */ + +#include "mapping.h" + +#include <unistd.h> +#include <sys/mman.h> + +int get_mapping(size_t length, int prot, int flags, + int fd, off_t offset, + void ** presult, void ** pmapping, size_t * pmapping_size) +{ + void * mapping; + size_t mapping_size; + void * result; + size_t page_size; + off_t delta; + + page_size = getpagesize(); + delta = offset % page_size; + + mapping = mmap(NULL, length + offset, prot, flags, fd, offset - delta); + if (mapping == (void *)MAP_FAILED) + return -1; + + result = ((char *) mapping) + delta; + + mapping_size = length + offset; + + * pmapping = mapping; + * pmapping_size = mapping_size; + * presult = result; + + return 0; +} Added: freeswitch/trunk/libs/libetpan/src/data-types/mapping.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mapping.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mapping.h,v 1.6 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef MAPPING_H + +#define MAPPING_H + +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +int get_mapping(size_t length, int prot, int flags, + int fd, off_t offset, + void ** presult, void ** pmapping, size_t * pmapping_size); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/md5.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/md5.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,572 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: md5.c,v 1.9 2006/06/02 15:44:29 smarinier Exp $ + */ + +/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm +*/ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. +*/ + +/* do i need all of this just for htonl()? damn. */ +#include <sys/types.h> +#ifndef _MSC_VER +# include <sys/param.h> +# include <sys/socket.h> +# include <netinet/in.h> +#endif + +#include "md5global.h" +#include "md5.h" +#include "hmac-md5.h" + +/* Constants for MD5Transform routine. +*/ + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static void MD5Transform PROTO_LIST ((UINT4 [4], const unsigned char [64])); +static void Encode PROTO_LIST + ((unsigned char *, UINT4 *, unsigned int)); +static void Decode PROTO_LIST + ((UINT4 *, const unsigned char *, unsigned int)); +static void MD5_memcpy PROTO_LIST ((POINTER, CONST_POINTER, unsigned int)); +static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int)); + +static unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* F, G, H and I are basic MD5 functions. + + */ +#ifdef I +/* This might be defined via NANA */ +#undef I +#endif + +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. + + */ + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +Rotation is separate from addition to prevent recomputation. +*/ + +#define FF(a, b, c, d, x, s, ac) { (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } +#define GG(a, b, c, d, x, s, ac) { (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } +#define HH(a, b, c, d, x, s, ac) { (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } +#define II(a, b, c, d, x, s, ac) { (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. +*/ + +void MD5Init (context) +MD5_CTX *context; /* context */ +{ + context->count[0] = context->count[1] = 0; + + /* Load magic initialization constants. + +*/ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* MD5 block update operation. Continues an MD5 message-digest + operation, processing another message block, and updating the context. +*/ + +void MD5Update (context, input, inputLen) +MD5_CTX *context; /* context */ +const unsigned char *input; /* input block */ +unsigned int inputLen; /* length of input block */ +{ + unsigned int i, index, partLen; + + /* Compute number of bytes mod 64 */ + index = (unsigned int)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((UINT4)inputLen << 3)) + < ((UINT4)inputLen << 3)) + context->count[1]++; + context->count[1] += ((UINT4)inputLen >> 29); + + partLen = 64 - index; + + /* Transform as many times as possible. + +*/ + if (inputLen >= partLen) { + MD5_memcpy + ((POINTER)&context->buffer[index], (POINTER)input, partLen); MD5Transform + (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform (context->state, &input[i]); + + index = 0; + } + else + i = 0; + + /* Buffer remaining input */ + MD5_memcpy + ((POINTER)&context->buffer[index], (POINTER)&input[i], + inputLen-i); + +} + +/* MD5 finalization. Ends an MD5 message-digest operation, writing the + the message digest and zeroizing the context. + + */ + +void MD5Final (digest, context) +unsigned char digest[16]; /* message digest */ +MD5_CTX *context; /* context */ +{ + unsigned char bits[8]; + unsigned int index, padLen; + + /* Save number of bits */ + Encode (bits, context->count, 8); + + /* Pad out to 56 mod 64. + +*/ + index = (unsigned int)((context->count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + MD5Update (context, PADDING, padLen); + + /* Append length (before padding) */ + MD5Update (context, bits, 8); + + /* Store state in digest */ + Encode (digest, context->state, 16); + + /* Zeroize sensitive information. + +*/ + MD5_memset ((POINTER)context, 0, sizeof (*context)); +} + +/* MD5 basic transformation. Transforms state based on block. + + */ + +static void MD5Transform (state, block) +UINT4 state[4]; +const unsigned char block[64]; +{ + UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode (x, block, 64); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. + */ + MD5_memset ((POINTER)x, 0, sizeof (x)); +} + +/* Encodes input (UINT4) into output (unsigned char). Assumes len is + a multiple of 4. + + */ + +static void Encode (output, input, len) +unsigned char *output; +UINT4 *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + +/* Decodes input (unsigned char) into output (UINT4). Assumes len is + a multiple of 4. + + */ + +static void Decode (output, input, len) +UINT4 *output; +const unsigned char *input; +unsigned int len; +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) + | (((UINT4)input[j+3]) << 24); +} + +/* Note: Replace "for loop" with standard memcpy if possible. + + */ + +static void MD5_memcpy (output, input, len) +POINTER output; +CONST_POINTER input; +unsigned int len; +{ + unsigned int i; + + for (i = 0; i < len; i++) + output[i] = input[i]; +} + +/* Note: Replace "for loop" with standard memset if possible. +*/ + +static void MD5_memset (output, value, len) +POINTER output; +int value; +unsigned int len; +{ + unsigned int i; + + for (i = 0; i < len; i++) + ((char *)output)[i] = (char)value; +} + +void hmac_md5_init(HMAC_MD5_CTX *hmac, + const unsigned char *key, + int key_len) +{ + unsigned char k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[65]; /* outer padding - + * key XORd with opad + */ + unsigned char tk[16]; + int i; + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) { + + MD5_CTX tctx; + + MD5Init(&tctx); + MD5Update(&tctx, key, key_len); + MD5Final(tk, &tctx); + + key = tk; + key_len = 16; + } + + /* + * the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + MD5_memset(k_ipad, '\0', sizeof k_ipad); + MD5_memset(k_opad, '\0', sizeof k_opad); + MD5_memcpy( k_ipad, key, key_len); + MD5_memcpy( k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + + MD5Init(&hmac->ictx); /* init inner context */ + MD5Update(&hmac->ictx, k_ipad, 64); /* apply inner pad */ + + MD5Init(&hmac->octx); /* init outer context */ + MD5Update(&hmac->octx, k_opad, 64); /* apply outer pad */ + + /* scrub the pads and key context (if used) */ + MD5_memset(&k_ipad[0], 0, sizeof(k_ipad)); + MD5_memset(&k_opad[0], 0, sizeof(k_opad)); + MD5_memset(&tk[0], 0, sizeof(tk)); + + /* and we're done. */ +} + +/* The precalc and import routines here rely on the fact that we pad + * the key out to 64 bytes and use that to initialize the md5 + * contexts, and that updating an md5 context with 64 bytes of data + * leaves nothing left over; all of the interesting state is contained + * in the state field, and none of it is left over in the count and + * buffer fields. So all we have to do is save the state field; we + * can zero the others when we reload it. Which is why the decision + * was made to pad the key out to 64 bytes in the first place. */ +void hmac_md5_precalc(HMAC_MD5_STATE *state, + const unsigned char *key, + int key_len) +{ + HMAC_MD5_CTX hmac; + unsigned lupe; + + hmac_md5_init(&hmac, key, key_len); + for (lupe = 0; lupe < 4; lupe++) { + state->istate[lupe] = htonl(hmac.ictx.state[lupe]); + state->ostate[lupe] = htonl(hmac.octx.state[lupe]); + } + MD5_memset((POINTER) &hmac, 0, sizeof(hmac)); +} + + +void hmac_md5_import(HMAC_MD5_CTX *hmac, + HMAC_MD5_STATE *state) +{ + unsigned lupe; + MD5_memset((POINTER) hmac, 0, sizeof(HMAC_MD5_CTX)); + for (lupe = 0; lupe < 4; lupe++) { + hmac->ictx.state[lupe] = ntohl(state->istate[lupe]); + hmac->octx.state[lupe] = ntohl(state->ostate[lupe]); + } + /* Init the counts to account for our having applied + * 64 bytes of key; this works out to 0x200 (64 << 3; see + * MD5Update above...) */ + hmac->ictx.count[0] = hmac->octx.count[0] = 0x200; +} + +void hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE], + HMAC_MD5_CTX *hmac) +{ + MD5Final(digest, &hmac->ictx); /* Finalize inner md5 */ + MD5Update(&hmac->octx, digest, 16); /* Update outer ctx */ + MD5Final(digest, &hmac->octx); /* Finalize outer md5 */ +} + + +void hmac_md5(text, text_len, key, key_len, digest) +const unsigned char* text; /* pointer to data stream */ +int text_len; /* length of data stream */ +const unsigned char* key; /* pointer to authentication key */ +int key_len; /* length of authentication key */ +unsigned char *digest; /* caller digest to be filled in */ +{ + MD5_CTX context; + + unsigned char k_ipad[65]; /* inner padding - + * key XORd with ipad + */ + unsigned char k_opad[65]; /* outer padding - + * key XORd with opad + */ + unsigned char tk[16]; + int i; + /* if key is longer than 64 bytes reset it to key=MD5(key) */ + if (key_len > 64) { + + MD5_CTX tctx; + + MD5Init(&tctx); + MD5Update(&tctx, key, key_len); + MD5Final(tk, &tctx); + + key = tk; + key_len = 16; + } + + /* + * the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + + /* start out by storing key in pads */ + MD5_memset(k_ipad, '\0', sizeof k_ipad); + MD5_memset(k_opad, '\0', sizeof k_opad); + MD5_memcpy( k_ipad, key, key_len); + MD5_memcpy( k_opad, key, key_len); + + /* XOR key with ipad and opad values */ + for (i=0; i<64; i++) { + k_ipad[i] ^= 0x36; + k_opad[i] ^= 0x5c; + } + /* + * perform inner MD5 + */ + + MD5Init(&context); /* init context for 1st + * pass */ + MD5Update(&context, k_ipad, 64); /* start with inner pad */ + MD5Update(&context, text, text_len); /* then text of datagram */ + MD5Final(digest, &context); /* finish up 1st pass */ + + /* + * perform outer MD5 + */ + MD5Init(&context); /* init context for 2nd + * pass */ + MD5Update(&context, k_opad, 64); /* start with outer pad */ + MD5Update(&context, digest, 16); /* then results of 1st + * hash */ + MD5Final(digest, &context); /* finish up 2nd pass */ + +} Added: freeswitch/trunk/libs/libetpan/src/data-types/md5.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/md5.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,88 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: md5.h,v 1.11 2006/06/02 15:44:29 smarinier Exp $ + */ + +/* MD5.H - header file for MD5C.C + */ + +/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. +These notices must be retained in any copies of any part of this +documentation and/or software. + */ + +#include "md5global.h" + +#ifndef MD5_H + +#define MD5_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* MD5 context. */ +typedef struct { + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; + +void MD5Init PROTO_LIST ((MD5_CTX *)); +void MD5Update PROTO_LIST + ((MD5_CTX *, const unsigned char *, unsigned int)); +void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); + +void hmac_md5 PROTO_LIST ((const unsigned char *, int, const unsigned char *, int, unsigned char *)); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/md5global.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/md5global.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,80 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: md5global.h,v 1.7 2006/06/02 15:44:29 smarinier Exp $ + */ + +/* GLOBAL.H - RSAREF types and constants + */ + +#ifndef MD5GLOBAL_H + +#define MD5GLOBAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* PROTOTYPES should be set to one if and only if the compiler supports + function argument prototyping. +The following makes PROTOTYPES default to 0 if it has not already + been defined with C compiler flags. + */ +#ifndef PROTOTYPES +#define PROTOTYPES 1 +#endif + +/* POINTER defines a generic pointer type */ +typedef unsigned char *POINTER; +typedef const unsigned char *CONST_POINTER; + +/* UINT2 defines a two byte word */ +typedef unsigned short int UINT2; + +/* UINT4 defines a four byte word */ +typedef unsigned long int UINT4; + +/* PROTO_LIST is defined depending on how PROTOTYPES is defined above. +If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it + returns an empty list. + */ +#if PROTOTYPES +#define PROTO_LIST(list) list +#else +#define PROTO_LIST(list) () +#endif + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/data-types/mmapstring.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mmapstring.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,583 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mmapstring.c,v 1.22 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mmapstring.h" + +#include "chash.h" + +#include <stdlib.h> +#ifdef _MSC_VER +# include "win_etpan.h" +#else +# include <unistd.h> +# include <sys/mman.h> +#endif +#include <string.h> +#ifdef LIBETPAN_REENTRANT +# ifndef WIN32 +# include <pthread.h> +# endif +#endif + +#include "libetpan-config.h" + +#define MMAPSTRING_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MMAPSTRING_MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define MMAP_STRING_DEFAULT_CEIL (8 * 1024 * 1024) + +#define DEFAULT_TMP_PATH "/tmp" + +static char tmpdir[PATH_MAX] = DEFAULT_TMP_PATH; + +static size_t mmap_string_ceil = MMAP_STRING_DEFAULT_CEIL; + +/* MMAPString references */ + +#ifdef LIBETPAN_REENTRANT +# ifdef WIN32 + + static CRITICAL_SECTION mmapstring_lock ; + static CRITICAL_SECTION* _get_critical() { + InitializeCriticalSection(&mmapstring_lock); + return &mmapstring_lock; + } + static int _lock_initialized = 0; + static void __mutex_lock(CRITICAL_SECTION* section) { + if (!_lock_initialized) + InitializeCriticalSection(section); + EnterCriticalSection( section); + } + static void __mutex_unlock(CRITICAL_SECTION* section) { + if (!_lock_initialized) + InitializeCriticalSection(section); + LeaveCriticalSection( section); + } +# define MUTEX_LOCK(x) __mutex_lock(x) +# define MUTEX_UNLOCK(x) __mutex_unlock(x) +# else + static pthread_mutex_t mmapstring_lock = PTHREAD_MUTEX_INITIALIZER; +# define MUTEX_LOCK(x) pthread_mutex_lock(x) +# define MUTEX_UNLOCK(x) pthread_mutex_unlock(x) +# endif +#else +# define MUTEX_LOCK(x) +# define MUTEX_UNLOCK(x) +#endif +static chash * mmapstring_hashtable = NULL; + +static void mmapstring_hashtable_init(void) +{ + mmapstring_hashtable = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); +} + +void mmap_string_set_tmpdir(char * directory) +{ + strncpy(tmpdir, directory, PATH_MAX); + tmpdir[PATH_MAX - 1] = 0; +} + + +int mmap_string_ref(MMAPString * string) +{ + chash * ht; + int r; + chashdatum key; + chashdatum data; + + MUTEX_LOCK(&mmapstring_lock); + + if (mmapstring_hashtable == NULL) { + mmapstring_hashtable_init(); + } + ht = mmapstring_hashtable; + + if (ht == NULL) { + + MUTEX_UNLOCK(&mmapstring_lock); + return -1; + } + + key.data = &string->str; + key.len = sizeof(string->str); + data.data = string; + data.len = 0; + + r = chash_set(mmapstring_hashtable, &key, &data, NULL); + + MUTEX_UNLOCK(&mmapstring_lock); + + if (r < 0) + return r; + + return 0; +} + +int mmap_string_unref(char * str) +{ + MMAPString * string; + chash * ht; + chashdatum key; + chashdatum data; + int r; + + MUTEX_LOCK(&mmapstring_lock); + + ht = mmapstring_hashtable; + + if (ht == NULL) { + + MUTEX_UNLOCK(&mmapstring_lock); + return -1; + } + + key.data = &str; + key.len = sizeof(str); + + r = chash_get(ht, &key, &data); + if (r < 0) + string = NULL; + else + string = data.data; + + if (string != NULL) { + chash_delete(ht, &key, NULL); + if (chash_count(ht) == 0) { + chash_free(ht); + mmapstring_hashtable = NULL; + } + } + + MUTEX_UNLOCK(&mmapstring_lock); + + if (string != NULL) { + mmap_string_free(string); + return 0; + } + else + return -1; +} + + + +/* MMAPString */ + +#define MY_MAXSIZE ((size_t) -1) + +static inline size_t +nearest_power (size_t base, size_t num) +{ + if (num > MY_MAXSIZE / 2) { + return MY_MAXSIZE; + } + else { + size_t n = base; + + while (n < num) + n <<= 1; + + return n; + } +} + +void mmap_string_set_ceil(size_t ceil) +{ + mmap_string_ceil = ceil; +} + +/* Strings. + */ + +/* SEB */ +#ifndef MMAP_UNAVAILABLE +static MMAPString * mmap_string_realloc_file(MMAPString * string) +{ + char * data; + + if (string->fd == -1) { + char tmpfilename[PATH_MAX]; + int fd; + + * tmpfilename = 0; + strcat(tmpfilename, tmpdir); + strcat(tmpfilename, "/libetpan-mmapstring-XXXXXX"); + + fd = mkstemp(tmpfilename); + if (fd == -1) + return NULL; + + if (unlink(tmpfilename) == -1) { + close(fd); + return NULL; + } + + if (ftruncate(fd, string->allocated_len) == -1) { + close(fd); + return NULL; + } + + data = mmap(NULL, string->allocated_len, PROT_WRITE | PROT_READ, + MAP_SHARED, fd, 0); + + if (data == (char *)MAP_FAILED) { + close(fd); + return NULL; + } + + if (string->str != NULL) + memcpy(data, string->str, string->len + 1); + + string->fd = fd; + string->mmapped_size = string->allocated_len; + free(string->str); + string->str = data; + } + else { + if (munmap(string->str, string->mmapped_size) == -1) + return NULL; + + if (ftruncate(string->fd, string->allocated_len) == -1) + return NULL; + + data = mmap(NULL, string->allocated_len, PROT_WRITE | PROT_READ, + MAP_SHARED, string->fd, 0); + + if (data == (char *)MAP_FAILED) + return NULL; + + string->mmapped_size = string->allocated_len; + string->str = data; + } + + return string; +} +#endif + +static MMAPString * mmap_string_realloc_memory(MMAPString * string) +{ + char * tmp; + + tmp = realloc (string->str, string->allocated_len); + + if (tmp == NULL) + string = NULL; + else + string->str = tmp; + + return string; +} + +static MMAPString * +mmap_string_maybe_expand (MMAPString* string, + size_t len) +{ + if (string->len + len >= string->allocated_len) + { + size_t old_size; + MMAPString * newstring; + + old_size = string->allocated_len; + + string->allocated_len = nearest_power (1, string->len + len + 1); + +#ifndef MMAP_UNAVAILABLE + if (string->allocated_len > mmap_string_ceil) + newstring = mmap_string_realloc_file(string); + else { +#endif + newstring = mmap_string_realloc_memory(string); +#ifndef MMAP_UNAVAILABLE + if (newstring == NULL) + newstring = mmap_string_realloc_file(string); + } +#endif + + if (newstring == NULL) + string->allocated_len = old_size; + + return newstring; + } + + return string; +} + +MMAPString* +mmap_string_sized_new (size_t dfl_size) +{ + MMAPString *string; + + string = malloc(sizeof(* string)); + if (string == NULL) + return NULL; + + string->allocated_len = 0; + string->len = 0; + string->str = NULL; + string->fd = -1; + string->mmapped_size = 0; + + if (mmap_string_maybe_expand (string, MMAPSTRING_MAX (dfl_size, 2)) == NULL) + return NULL; + + string->str[0] = 0; + + return string; +} + +MMAPString* +mmap_string_new (const char *init) +{ + MMAPString *string; + + string = mmap_string_sized_new (init ? strlen (init) + 2 : 2); + if (string == NULL) + return NULL; + + if (init) + mmap_string_append (string, init); + + return string; +} + +MMAPString* +mmap_string_new_len (const char *init, + size_t len) +{ + MMAPString *string; + + if (len <= 0) + return mmap_string_new (""); + else + { + string = mmap_string_sized_new (len); + if (string == NULL) + return string; + + if (init) + mmap_string_append_len (string, init, len); + + return string; + } +} + +void +mmap_string_free (MMAPString *string) +{ + if (string == NULL) + return; + +/* SEB */ +#ifndef MMAP_UNAVAILABLE + if (string->fd != -1) { + munmap(string->str, string->mmapped_size); + close(string->fd); + } + else +#endif + { + free (string->str); + } + free(string); +} + +MMAPString* +mmap_string_assign (MMAPString *string, + const char *rval) +{ + mmap_string_truncate (string, 0); + if (mmap_string_append (string, rval) == NULL) + return NULL; + + return string; +} + +MMAPString* +mmap_string_truncate (MMAPString *string, + size_t len) +{ + string->len = MMAPSTRING_MIN (len, string->len); + string->str[string->len] = 0; + + return string; +} + +/** + * mmap_string_set_size: + * @string: a #MMAPString + * @len: the new length + * + * Sets the length of a #MMAPString. If the length is less than + * the current length, the string will be truncated. If the + * length is greater than the current length, the contents + * of the newly added area are undefined. (However, as + * always, string->str[string->len] will be a nul byte.) + * + * Return value: @string + **/ +MMAPString* +mmap_string_set_size (MMAPString *string, + size_t len) +{ + if (len >= string->allocated_len) + if (mmap_string_maybe_expand (string, len - string->len) == NULL) + return NULL; + + string->len = len; + string->str[len] = 0; + + return string; +} + +/* +static int in_mapped_zone(MMAPString * string, char * val) +{ + return (val >= string->str) && (val < string->str + string->mmapped_size); +} +*/ + +MMAPString* +mmap_string_insert_len (MMAPString *string, + size_t pos, + const char *val, + size_t len) +{ + if (mmap_string_maybe_expand (string, len) == NULL) + return NULL; + + if (pos < string->len) + memmove (string->str + pos + len, string->str + pos, string->len - pos); + + /* insert the new string */ + memmove (string->str + pos, val, len); + + string->len += len; + + string->str[string->len] = 0; + + return string; +} + +MMAPString* +mmap_string_append (MMAPString *string, + const char *val) +{ + return mmap_string_insert_len (string, string->len, val, strlen(val)); +} + +MMAPString* +mmap_string_append_len (MMAPString *string, + const char *val, + size_t len) +{ + return mmap_string_insert_len (string, string->len, val, len); +} + +MMAPString* +mmap_string_append_c (MMAPString *string, + char c) +{ + return mmap_string_insert_c (string, string->len, c); +} + +MMAPString* +mmap_string_prepend (MMAPString *string, + const char *val) +{ + return mmap_string_insert_len (string, 0, val, strlen(val)); +} + +MMAPString* +mmap_string_prepend_len (MMAPString *string, + const char *val, + size_t len) +{ + return mmap_string_insert_len (string, 0, val, len); +} + +MMAPString* +mmap_string_prepend_c (MMAPString *string, + char c) +{ + return mmap_string_insert_c (string, 0, c); +} + +MMAPString* +mmap_string_insert (MMAPString *string, + size_t pos, + const char *val) +{ + return mmap_string_insert_len (string, pos, val, strlen(val)); +} + +MMAPString* +mmap_string_insert_c (MMAPString *string, + size_t pos, + char c) +{ + if (mmap_string_maybe_expand (string, 1) == NULL) + return NULL; + + /* If not just an append, move the old stuff */ + if (pos < string->len) + memmove (string->str + pos + 1, string->str + pos, string->len - pos); + + string->str[pos] = c; + + string->len += 1; + + string->str[string->len] = 0; + + return string; +} + +MMAPString* +mmap_string_erase (MMAPString *string, + size_t pos, + size_t len) +{ + if ((pos + len) < string->len) + memmove (string->str + pos, string->str + pos + len, + string->len - (pos + len)); + + string->len -= len; + + string->str[string->len] = 0; + + return string; +} Added: freeswitch/trunk/libs/libetpan/src/data-types/mmapstring.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/data-types/mmapstring.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,156 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mmapstring.h,v 1.13 2006/03/22 08:10:47 hoa Exp $ + */ + +#ifndef __MMAP_STRING_H__ + +#define __MMAP_STRING_H__ + +#include <sys/types.h> + +#ifndef LIBETPAN_CONFIG_H +# include <libetpan/libetpan-config.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* +#define TMPDIR "/tmp" +*/ + +typedef struct _MMAPString MMAPString; + +struct _MMAPString +{ + char * str; + size_t len; + size_t allocated_len; + int fd; + size_t mmapped_size; + /* + char * old_non_mmapped_str; + */ +}; + +/* configure location of mmaped files */ + +void mmap_string_set_tmpdir(char * directory); + +/* Strings + */ +LIBETPAN_EXPORT +MMAPString * mmap_string_new (const char * init); + +LIBETPAN_EXPORT +MMAPString * mmap_string_new_len (const char * init, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_sized_new (size_t dfl_size); + +LIBETPAN_EXPORT +void mmap_string_free (MMAPString * string); + +LIBETPAN_EXPORT +MMAPString * mmap_string_assign (MMAPString * string, + const char * rval); + +LIBETPAN_EXPORT +MMAPString * mmap_string_truncate (MMAPString *string, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_set_size (MMAPString * string, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_insert_len (MMAPString * string, + size_t pos, + const char * val, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_append (MMAPString * string, + const char * val); + +LIBETPAN_EXPORT +MMAPString * mmap_string_append_len (MMAPString * string, + const char * val, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_append_c (MMAPString * string, + char c); + +LIBETPAN_EXPORT +MMAPString * mmap_string_prepend (MMAPString * string, + const char * val); + +LIBETPAN_EXPORT +MMAPString * mmap_string_prepend_c (MMAPString * string, + char c); + +LIBETPAN_EXPORT +MMAPString * mmap_string_prepend_len (MMAPString * string, + const char * val, + size_t len); + +LIBETPAN_EXPORT +MMAPString * mmap_string_insert (MMAPString * string, + size_t pos, + const char * val); + +LIBETPAN_EXPORT +MMAPString * mmap_string_insert_c (MMAPString *string, + size_t pos, + char c); + +LIBETPAN_EXPORT +MMAPString * mmap_string_erase(MMAPString * string, + size_t pos, + size_t len); + +void mmap_string_set_ceil(size_t ceil); + +int mmap_string_ref(MMAPString * string); +int mmap_string_unref(char * str); + +#ifdef __cplusplus +} +#endif + + +#endif /* __MMAP_STRING_H__ */ Added: freeswitch/trunk/libs/libetpan/src/driver/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,2 @@ +.libs +*.la Added: freeswitch/trunk/libs/libetpan/src/driver/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,15 @@ +top_builddir = ../.. + +SUBLIBS = interface/libinterface.la \ + tools/libtools.la \ + implementation/libimplementation.la + + +SUBDIRS = interface \ + tools \ + implementation + + +TARGET = libdriver + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/driver/TODO ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/TODO Wed Dec 20 15:28:56 2006 @@ -0,0 +1,9 @@ +- get_message_list() will disconnect and reconnect POP3 box +- add UID to non-cached drivers, help clients to recognize messages +- move IMAP UID cache to non-cached driver +- fix message size (put it in cache) +- XXX : fetch body in nntp do not use generic_fetch_body +- add flags prototype to add or remove flags +- cache bodystructures +- search is not implemented +- list of folder new implementation Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,2 @@ +.libs +*.la Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,28 @@ +SUBLIBS = data-message/libdata-message.la \ + imap/libimap.la \ + maildir/libmaildir.la \ + mbox/libmbox.la \ + mh/libmh.la \ + mime-message/libmime-message.la \ + nntp/libnntp.la \ + pop3/libpop3.la \ + hotmail/libhotmail.la \ + db/libdb.la + + +SUBDIRS = data-message \ + imap \ + maildir \ + mbox \ + mh \ + mime-message \ + nntp \ + pop3 \ + hotmail \ + db + + +TARGET = libimplementation + +top_builddir = ../../.. +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/data-message/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/data-message/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/data-message/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/data-message/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,14 @@ +top_builddir = ../../../.. + +HEADERS = \ + data_message_driver.h + + +SOURCES = \ + data_message_driver.c + + +TARGET = libdata-message +INCLUDES = -I../../interface + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/data-message/data_message_driver.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/data-message/data_message_driver.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,152 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: data_message_driver.c,v 1.10 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "data_message_driver.h" + +#include "mailmessage.h" +#include "mailmessage_tools.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> + +static int fetch_size(mailmessage * msg, size_t * result) +{ + struct generic_message_t * msg_data; + + msg_data = msg->msg_data; + * result = msg_data->msg_length; + + return MAIL_NO_ERROR; +} + + +static mailmessage_driver local_data_message_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* msg_name */ "data", + + /* msg_initialize */ mailmessage_generic_initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ NULL, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mailmessage_generic_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ NULL, +#else + .msg_name = "data", + + .msg_initialize = mailmessage_generic_initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = NULL, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mailmessage_generic_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = NULL, +#endif +}; + +mailmessage_driver * data_message_driver = &local_data_message_driver; + + + +mailmessage * data_message_init(char * data, size_t len) +{ + struct generic_message_t * msg_data; + mailmessage * msg; + int r; + + msg = mailmessage_new(); + if (msg == NULL) + goto err; + + r = mailmessage_init(msg, NULL, data_message_driver, 0, len); + if (r < 0) + goto free; + + msg_data = msg->msg_data; + msg_data->msg_fetched = 1; + msg_data->msg_message = data; + msg_data->msg_length = len; + + return msg; + + free: + mailmessage_free(msg); + err: + return NULL; +} + +void data_message_detach_mime(mailmessage * msg) +{ + msg->msg_mime = NULL; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/data-message/data_message_driver.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/data-message/data_message_driver.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,50 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: data_message_driver.h,v 1.4 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef DATA_MESSAGE_DRIVER_H + +#define DATA_MESSAGE_DRIVER_H + +#include <libetpan/mailmessage.h> + +#define LIBETPAN_DATA_MESSAGE + +extern mailmessage_driver * data_message_driver; + +mailmessage * data_message_init(char * data, size_t len); + +void data_message_detach_mime(mailmessage * msg); + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/db/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/db/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/db/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/db/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,24 @@ +top_builddir = ../../../.. + +HEADERS = \ + dbdriver.h \ + dbdriver_message.h \ + dbdriver_types.h \ + dbstorage.h + + +SOURCES = \ + dbdriver.c \ + dbdriver_message.c \ + dbstorage.c + + +TARGET = libdb +INCLUDES = -I../../interface \ + -I../../tools \ + -I$(srcdir)/low-level/mime \ + -I$(srcdir)/low-level/imf \ + -I$(srcdir)/data-types + + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbdriver.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbdriver.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1192 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbdriver.c,v 1.11 2006/10/24 21:57:51 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "dbdriver.h" +#include "imfcache.h" +#include "generic_cache.h" +#include "libetpan-config.h" +#include "dbdriver_message.h" +#include "mail_cache_db.h" +#include <string.h> +#include <stdlib.h> +#include "mailmessage.h" + +static int initialize(mailsession * session); + +static void uninitialize(mailsession * session); + +static int connect_path(mailsession * session, const char * path); + +static int logout(mailsession * session); + +static int expunge_folder(mailsession * session); + +static int status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int recent_number(mailsession * session, const char * mb, + uint32_t * result); + +static int unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +static int messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int append_message(mailsession * session, + const char * message, size_t size); + +static int append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int check_folder(mailsession * session); + +static int get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + +static mailsession_driver local_db_session_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sess_name */ "db", + + /* sess_initialize */ initialize, + /* sess_uninitialize */ uninitialize, + + /* sess_parameters */ NULL, + + /* sess_connect_stream */ NULL, + /* sess_connect_path */ connect_path, + /* sess_starttls */ NULL, + /* sess_login */ NULL, + /* sess_logout */ logout, + /* sess_noop */ NULL, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ check_folder, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ NULL, + /* sess_expunge_folder */ expunge_folder, + /* sess_status_folder */ status_folder, + /* sess_messages_number */ messages_number, + /* sess_recent_number */ recent_number, + /* sess_unseen_number */ unseen_number, + /* sess_list_folders */ NULL, + /* sess_lsub_folders */ NULL, + /* sess_subscribe_folder */ NULL, + /* sess_unsubscribe_folder */ NULL, + + /* sess_append_message */ append_message, + /* sess_append_message_flags */ append_message_flags, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ get_message, + /* sess_get_message_by_uid */ get_message_by_uid, + + /* sess_get_messages_list */ get_messages_list, + /* sess_get_envelopes_list */ get_envelopes_list, + /* sess_remove_message */ NULL, + /* sess_login_sasl */ NULL, + +#else + .sess_name = "db", + + .sess_initialize = initialize, + .sess_uninitialize = uninitialize, + + .sess_parameters = NULL, + + .sess_connect_stream = NULL, + .sess_connect_path = connect_path, + .sess_starttls = NULL, + .sess_login = NULL, + .sess_logout = logout, + .sess_noop = NULL, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = check_folder, + .sess_examine_folder = NULL, + .sess_select_folder = NULL, + .sess_expunge_folder = expunge_folder, + .sess_status_folder = status_folder, + .sess_messages_number = messages_number, + .sess_recent_number = recent_number, + .sess_unseen_number = unseen_number, + .sess_list_folders = NULL, + .sess_lsub_folders = NULL, + .sess_subscribe_folder = NULL, + .sess_unsubscribe_folder = NULL, + + .sess_append_message = append_message, + .sess_append_message_flags = append_message_flags, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = get_messages_list, + .sess_get_envelopes_list = get_envelopes_list, + .sess_remove_message = NULL, + + .sess_get_message = get_message, + .sess_get_message_by_uid = get_message_by_uid, + .sess_login_sasl = NULL, +#endif +}; + +mailsession_driver * db_session_driver = &local_db_session_driver; + +static inline struct db_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static int flags_store_process(mailsession * session) +{ + unsigned int i; + MMAPString * mmapstr; + int r; + int res; + struct mail_cache_db * maildb; + struct db_session_state_data * data; + struct mail_flags_store * flags_store; + + data = get_data(session); + + flags_store = data->db_flags_store; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mail_cache_db_open_lock(data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + char key[PATH_MAX]; + + msg = carray_get(flags_store->fls_tab, i); + + snprintf(key, sizeof(key), "%lu-flags", (unsigned long) msg->msg_index); + + r = generic_cache_flags_write(maildb, mmapstr, + key, msg->msg_flags); + } + + mail_flags_store_clear(flags_store); + + mail_cache_db_close_unlock(data->db_filename, maildb); + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int db_get_next_validity(struct mail_cache_db * maildb, + uint32_t * p_validity) +{ + int r; + char key_value[PATH_MAX]; + uint32_t validity; + void * serialized; + size_t serialized_len; + int res; + MMAPString * mmapstr; + size_t cur_token; + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(key_value, sizeof(key_value), "next-validity"); + + r = mail_cache_db_get(maildb, key_value, strlen(key_value), + &serialized, &serialized_len); + + if (r >= 0) { + size_t cur_token; + + if (mmap_string_append_len(mmapstr, serialized, serialized_len) == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + cur_token = 0; + r = mailimf_cache_int_read(mmapstr, &cur_token, &validity); + if (r < 0) + validity = 0; + } + else { + validity = 0; + } + + mmap_string_set_size(mmapstr, 0); + cur_token = 0; + r = mailimf_cache_int_write(mmapstr, &cur_token, validity + 1); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_put(maildb, key_value, strlen(key_value), + mmapstr->str, mmapstr->len); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + mmap_string_free(mmapstr); + + * p_validity = validity; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int db_get_next_msg_number(struct mail_cache_db * maildb, + uint32_t * p_num) +{ + int r; + char key_value[PATH_MAX]; + uint32_t num; + void * serialized; + size_t serialized_len; + int res; + MMAPString * mmapstr; + size_t cur_token; + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(key_value, sizeof(key_value), "next-msg"); + + r = mail_cache_db_get(maildb, key_value, strlen(key_value), + &serialized, &serialized_len); + + if (r >= 0) { + size_t cur_token; + + if (mmap_string_append_len(mmapstr, serialized, serialized_len) == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + cur_token = 0; + r = mailimf_cache_int_read(mmapstr, &cur_token, &num); + if (r < 0) + num = 1; + } + else { + num = 1; + } + + mmap_string_set_size(mmapstr, 0); + cur_token = 0; + r = mailimf_cache_int_write(mmapstr, &cur_token, num + 1); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_put(maildb, key_value, strlen(key_value), + mmapstr->str, mmapstr->len); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto free_mmapstr; + } + + mmap_string_free(mmapstr); + + * p_num = num; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int db_set_message_list(struct mail_cache_db * maildb, + carray * msglist) +{ + MMAPString * mmapstr; + char key_value[PATH_MAX]; + int r; + unsigned int i; + size_t cur_token; + int res; + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + cur_token = 0; + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t * msg; + + msg = carray_get(msglist, i); + r = mailimf_cache_int_write(mmapstr, &cur_token, * msg); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + } + + snprintf(key_value, sizeof(key_value), "message-list"); + r = mail_cache_db_put(maildb, key_value, strlen(key_value), + mmapstr->str, mmapstr->len); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int db_get_message_list(struct mail_cache_db * maildb, + carray ** p_msglist) +{ + carray * msglist; + void * serialized; + size_t serialized_len; + int r; + char key_value[PATH_MAX]; + int res; + unsigned int i; + + msglist = carray_new(16); + if (msglist == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(key_value, sizeof(key_value), "message-list"); + r = mail_cache_db_get(maildb, key_value, strlen(key_value), + &serialized, &serialized_len); + if (r >= 0) { + MMAPString * mmapstr; + size_t cur_token; + + /* collect message list */ + + mmapstr = mmap_string_new_len(serialized, serialized_len); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_msglist; + } + + cur_token = 0; + do { + uint32_t num; + uint32_t * msg; + + r = mailimf_cache_int_read(mmapstr, &cur_token, &num); + if (r != MAIL_NO_ERROR) + break; + + msg = malloc(sizeof(* msg)); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + mmap_string_free(mmapstr); + goto free_msglist; + } + * msg = num; + + r = carray_add(msglist, msg, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + free(msg); + mmap_string_free(mmapstr); + goto free_msglist; + } + } while (1); + + mmap_string_free(mmapstr); + } + + * p_msglist = msglist; + + return MAIL_NO_ERROR; + + free_msglist: + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t * msg; + + msg = carray_get(msglist, i); + free(msg); + } + carray_free(msglist); + err: + return res; +} + +static int initialize(mailsession * session) +{ + struct db_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->db_filename[0] = '\0'; + + data->db_flags_store = mail_flags_store_new(); + if (data->db_flags_store == NULL) + goto free; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void uninitialize(mailsession * session) +{ + struct db_session_state_data * data; + + data = get_data(session); + + flags_store_process(session); + + mail_flags_store_free(data->db_flags_store); + + free(data); + + session->sess_data = NULL; +} + +static int connect_path(mailsession * session, const char * path) +{ + struct db_session_state_data * data; + + data = get_data(session); + + strncpy(data->db_filename, path, sizeof(data->db_filename)); + + return MAIL_NO_ERROR; +} + +static int logout(mailsession * session) +{ + return MAIL_NO_ERROR; +} + +static int expunge_folder(mailsession * session) +{ + int r; + char key_value[PATH_MAX]; + struct mail_cache_db * maildb; + carray * msglist; + unsigned int i; + struct db_session_state_data * data; + int res; + chash * msg_table; + MMAPString * mmapstr; + + data = get_data(session); + + flags_store_process(session); + + r = mail_cache_db_open_lock(data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + r = db_get_message_list(maildb, &msglist); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_db; + } + + msg_table = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (msg_table == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_msglist; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_msgtable; + } + + i = 0; + while (i < carray_count(msglist)) { + uint32_t num; + uint32_t * msg; + chashdatum key; + chashdatum value; + struct mail_flags * flags; + int deleted; + + msg = carray_get(msglist, i); + num = * msg; + + deleted = 0; + snprintf(key_value, sizeof(key_value), "%lu-flags", + (unsigned long) num); + r = generic_cache_flags_read(maildb, mmapstr, key_value, &flags); + if (r == MAIL_NO_ERROR) { + if ((flags->fl_flags & MAIL_FLAG_DELETED) != 0) + deleted = 1; + } + + if (!deleted) { + snprintf(key_value, sizeof(key_value), "%lu", (unsigned long) num); + key.data = key_value; + key.len = strlen(key_value); + chash_set(msg_table, &key, &value, NULL); + + snprintf(key_value, sizeof(key_value), "%lu-envelope", + (unsigned long) num); + key.data = key_value; + key.len = strlen(key_value); + chash_set(msg_table, &key, &value, NULL); + + snprintf(key_value, sizeof(key_value), "%lu-flags", + (unsigned long) num); + key.data = key_value; + key.len = strlen(key_value); + chash_set(msg_table, &key, &value, NULL); + + i ++; + } + else { + free(msg); + carray_delete(msglist, i); + } + } + + mmap_string_free(mmapstr); + + r = mail_cache_db_clean_up(maildb, msg_table); + + chash_free(msg_table); + + r = db_set_message_list(maildb, msglist); + + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t * msg; + + msg = carray_get(msglist, i); + free(msg); + } + carray_free(msglist); + + mail_cache_db_close_unlock(data->db_filename, maildb); + + return MAIL_NO_ERROR; + + free_msgtable: + chash_free(msg_table); + free_msglist: + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t * msg; + + msg = carray_get(msglist, i); + free(msg); + } + close_db: + mail_cache_db_close_unlock(data->db_filename, maildb); + err: + return res; +} + +static int status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + struct mail_cache_db * maildb; + char key_value[PATH_MAX]; + MMAPString * mmapstr; + uint32_t messages; + uint32_t recent; + uint32_t unseen; + struct db_session_state_data * data; + int r; + int res; + carray * msglist; + unsigned int i; + + data = get_data(session); + + flags_store_process(session); + + r = mail_cache_db_open_lock(data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + r = db_get_message_list(maildb, &msglist); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_db; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + messages = 0; + recent = 0; + unseen = 0; + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t num; + uint32_t * msg; + int r; + struct mail_flags * flags; + + msg = carray_get(msglist, i); + num = * msg; + free(msg); + carray_set(msglist, i, NULL); + + messages ++; + + snprintf(key_value, sizeof(key_value), "%lu-flags", (unsigned long) num); + + r = generic_cache_flags_read(maildb, mmapstr, key_value, &flags); + if (r == MAIL_NO_ERROR) { + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + mail_flags_free(flags); + } + } + + mmap_string_free(mmapstr); + + carray_free(msglist); + + mail_cache_db_close_unlock(data->db_filename, maildb); + + * result_messages = messages; + * result_unseen = unseen; + * result_recent = recent; + + return MAIL_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t * msg; + + msg = carray_get(msglist, i); + if (msg != NULL) + free(msg); + } + carray_free(msglist); + close_db: + mail_cache_db_close_unlock(data->db_filename, maildb); + err: + return res; +} + +static int recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t dummy_messages; + uint32_t dummy_unseen; + + return status_folder(session, mb, + &dummy_messages, result, &dummy_unseen); +} + +static int unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t dummy_messages; + uint32_t dummy_recent; + + return status_folder(session, mb, + &dummy_messages, &dummy_recent, result); +} + +static int messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t dummy_unseen; + uint32_t dummy_recent; + + return status_folder(session, mb, + result, &dummy_recent, &dummy_unseen); +} + +static int append_message(mailsession * session, + const char * message, size_t size) +{ + return append_message_flags(session, message, size, NULL); +} + +static int append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + carray * msglist; + unsigned int i; + uint32_t * msg; + uint32_t num; + char key_value[PATH_MAX]; + MMAPString * mmapstr; + struct mail_cache_db * maildb; + struct db_session_state_data * data; + size_t cur_token; + struct mailimf_fields * fields; + int r; + int res; + + data = get_data(session); + + r = mail_cache_db_open_lock(data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + num = 0; + r = db_get_next_msg_number(maildb, &num); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = db_get_message_list(maildb, &msglist); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_db; + } + + msg = malloc(sizeof(* msg)); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_msglist; + } + + * msg = num; + + r = carray_add(msglist, msg, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + free(msg); + goto free_msglist; + } + + r = db_set_message_list(maildb, msglist); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_msglist; + } + + /* free msglist */ + + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t * msg; + + msg = carray_get(msglist, i); + free(msg); + } + carray_free(msglist); + + snprintf(key_value, sizeof(key_value), "%lu", (unsigned long) num); + + r = mail_cache_db_put(maildb, key_value, strlen(key_value), + message, size); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db; + } + + /* write envelope */ + + cur_token = 0; + r = mailimf_envelope_fields_parse(message, size, &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_PARSE; + goto close_db; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + cur_token = 0; + r = mailimf_cache_fields_write(mmapstr, &cur_token, fields); + if (r != MAIL_NO_ERROR) { + res = r; + mmap_string_free(mmapstr); + goto close_db; + } + + snprintf(key_value, sizeof(key_value), "%lu-envelope", (unsigned long) num); + + r = mail_cache_db_put(maildb, key_value, strlen(key_value), + mmapstr->str, mmapstr->len); + + mmap_string_free(mmapstr); + + mailimf_fields_free(fields); + + /* write flags */ + + if (flags != NULL) { + snprintf(key_value, sizeof(key_value), "%lu-flags", (unsigned long) num); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + r = generic_cache_flags_write(maildb, mmapstr, + key_value, flags); + + mmap_string_free(mmapstr); + + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FILE; + goto close_db; + } + } + + mail_cache_db_close_unlock(data->db_filename, maildb); + + return MAIL_NO_ERROR; + + free_msglist: + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t * msg; + + msg = carray_get(msglist, i); + free(msg); + } + carray_free(msglist); + close_db: + mail_cache_db_close_unlock(data->db_filename, maildb); + err: + return res; +} + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + int r; + char key[PATH_MAX]; + struct mail_cache_db * maildb; + struct db_session_state_data * data; + int res; + carray * msglist; + unsigned int i; + carray * msgtab; + struct mailmessage_list * driver_msglist; + + data = get_data(session); + + r = mail_cache_db_open_lock(data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + r = db_get_message_list(maildb, &msglist); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_db; + } + + msgtab = carray_new(16); + if (msgtab == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t msg_num; + uint32_t * pmsg_num; + mailmessage * msg; + size_t size; + + pmsg_num = carray_get(msglist, i); + msg_num = * pmsg_num; + free(pmsg_num); + carray_set(msglist, i, NULL); + + snprintf(key, sizeof(key), "%lu", (unsigned long) msg_num); + r = mail_cache_db_get_size(maildb, key, strlen(key), &size); + if (r < 0) { + continue; + } + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, db_message_driver, + msg_num, size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto free_list; + } + + r = carray_add(msgtab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + carray_free(msglist); + + driver_msglist = mailmessage_list_new(msgtab); + if (driver_msglist == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + mail_cache_db_close_unlock(data->db_filename, maildb); + + * result = driver_msglist; + + return MAIL_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(msgtab) ; i ++) { + mailmessage * msg; + + msg = carray_get(msgtab, i); + mailmessage_free(msg); + } + carray_free(msgtab); + + for(i = 0 ; i < carray_count(msglist) ; i ++) { + uint32_t * msg; + + msg = carray_get(msglist, i); + if (msg != NULL) + free(msg); + } + carray_free(msglist); + close_db: + mail_cache_db_close_unlock(data->db_filename, maildb); + err: + return res; +} + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + unsigned int i; + char key[PATH_MAX]; + int r; + struct mail_cache_db * maildb; + int res; + struct db_session_state_data * data; + MMAPString * mmapstr; + + data = get_data(session); + + flags_store_process(session); + + r = mail_cache_db_open_lock(data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + if (msg->msg_fields == NULL) { + snprintf(key, sizeof(key), "%lu-envelope", + (unsigned long) msg->msg_index); + + r = generic_cache_fields_read(maildb, mmapstr, + key, &msg->msg_fields); + } + + if (msg->msg_flags == NULL) { + snprintf(key, sizeof(key), "%lu-flags", + (unsigned long) msg->msg_index); + + r = generic_cache_flags_read(maildb, mmapstr, + key, &msg->msg_flags); + } + } + + mmap_string_free(mmapstr); + + mail_cache_db_close_unlock(data->db_filename, maildb); + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(data->db_filename, maildb); + err: + return res; +} + +static int check_folder(mailsession * session) +{ + flags_store_process(session); + + return MAIL_NO_ERROR; +} + +static int get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg; + int r; + size_t size; + char key[PATH_MAX]; + struct db_session_state_data * data; + struct mail_cache_db * maildb; + int res; + + data = get_data(session); + + r = mail_cache_db_open_lock(data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + size = 0; + snprintf(key, sizeof(key), "%lu", (unsigned long) num); + r = mail_cache_db_get_size(maildb, key, strlen(key), &size); + /* ignore error */ + + r = mailmessage_init(msg, session, db_message_driver, + num, size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto close_db; + } + + mail_cache_db_close_unlock(data->db_filename, maildb); + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(data->db_filename, maildb); + err: + return res; +} + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result) +{ + uint32_t msg_num; + + msg_num = strtoul(uid, NULL, 10); + + return get_message(session, msg_num, result); +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbdriver.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbdriver.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbdriver.h,v 1.2 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef DBDRIVER_H + +#define DBDRIVER_H + +#include <libetpan/dbdriver_message.h> +#include <libetpan/dbdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * db_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbdriver_message.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbdriver_message.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,337 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbdriver_message.c,v 1.6 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "dbdriver_message.h" +#include "dbdriver.h" +#include "mail_cache_db.h" + +#include "mailmessage_tools.h" +#include "generic_cache.h" + +#include <unistd.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> + +static int fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + +static int get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static int prefetch(mailmessage * msg_info); + +static void prefetch_free(struct generic_message_t * msg); + +static int initialize(mailmessage * msg_info); + +static void check(mailmessage * msg_info); + +static mailmessage_driver local_db_message_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* msg_name */ "db", + + /* msg_initialize */ initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ check, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mailmessage_generic_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_header, + /* msg_fetch_size */ NULL, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ fetch_envelope, + + /* msg_get_flags */ get_flags, +#else + .msg_name = "db", + + .msg_initialize = initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = check, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mailmessage_generic_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_header, + .msg_fetch_size = NULL, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = fetch_envelope, + + .msg_get_flags = get_flags, +#endif +}; + +mailmessage_driver * db_message_driver = &local_db_message_driver; + +struct db_msg_data { + MMAPString * msg_content; +}; + +static inline struct db_session_state_data * +get_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static int prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int res; + struct db_msg_data * data; + struct db_session_state_data * sess_data; + MMAPString * msg_content; + struct mail_cache_db * maildb; + int r; + char key[PATH_MAX]; + void * msg_data; + size_t msg_data_len; + + sess_data = get_session_data(msg_info); + + r = mail_cache_db_open_lock(sess_data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + snprintf(key, sizeof(key), "%lu", (unsigned long) msg_info->msg_index); + r = mail_cache_db_get(maildb, key, strlen(key), &msg_data, &msg_data_len); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto close_db; + } + + msg_content = mmap_string_new_len(msg_data, msg_data_len); + if (msg_content == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + data = malloc(sizeof(* data)); + if (data == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + data->msg_content = msg_content; + + msg = msg_info->msg_data; + + msg->msg_data = data; + msg->msg_message = msg_content->str; + msg->msg_length = msg_content->len; + + mail_cache_db_close_unlock(sess_data->db_filename, maildb); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(msg_content); + close_db: + mail_cache_db_close_unlock(sess_data->db_filename, maildb); + err: + return res; +} + +static void prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + struct db_msg_data * data; + + data = msg->msg_data; + mmap_string_free(data->msg_content); + data->msg_content = NULL; + free(data); + msg->msg_message = NULL; + } +} + +static int initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char key[PATH_MAX]; + + snprintf(key, sizeof(key), "%lu", (unsigned long) msg_info->msg_index); + msg_info->msg_uid = strdup(key); + if (msg_info->msg_uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + msg->msg_prefetch = prefetch; + msg->msg_prefetch_free = prefetch_free; + + return MAIL_NO_ERROR; +} + +static void check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_session_data(msg_info)->db_flags_store, + msg_info); + /* ignore errors */ + } +} + +static int fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result) +{ + char key[PATH_MAX]; + int r; + struct db_session_state_data * sess_data; + struct mail_cache_db * maildb; + int res; + struct mailimf_fields * fields; + MMAPString * mmapstr; + + sess_data = get_session_data(msg_info); + + r = mail_cache_db_open_lock(sess_data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + snprintf(key, sizeof(key), "%lu-envelope", + (unsigned long) msg_info->msg_index); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + r = generic_cache_fields_read(maildb, mmapstr, + key, &fields); + + mmap_string_free(mmapstr); + + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto close_db; + } + + mail_cache_db_close_unlock(sess_data->db_filename, maildb); + + * result = fields; + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(sess_data->db_filename, maildb); + err: + return res; +} + +static int get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + char key[PATH_MAX]; + int r; + struct db_session_state_data * sess_data; + struct mail_cache_db * maildb; + int res; + MMAPString * mmapstr; + + sess_data = get_session_data(msg_info); + + r = mail_cache_db_open_lock(sess_data->db_filename, &maildb); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + snprintf(key, sizeof(key), "%lu-flags", (unsigned long) msg_info->msg_index); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + r = generic_cache_flags_read(maildb, mmapstr, + key, &msg_info->msg_flags); + + mmap_string_free(mmapstr); + + if (r != MAIL_NO_ERROR) { + msg_info->msg_flags = mail_flags_new_empty(); + if (msg_info->msg_flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + } + + mail_cache_db_close_unlock(sess_data->db_filename, maildb); + + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(sess_data->db_filename, maildb); + err: + return res; +} + Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbdriver_message.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbdriver_message.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbdriver_message.h,v 1.2 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef DBDRIVER_MESSAGE_H + +#define DBDRIVER_MESSAGE_H + +#include <libetpan/dbdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * db_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbdriver_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbdriver_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,71 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbdriver_types.h,v 1.2 2004/11/21 21:53:31 hoa Exp $ + */ + +#ifndef DBDRIVER_TYPES_H + +#define DBDRIVER_TYPES_H + +#include <libetpan/libetpan-config.h> + +#include <libetpan/maildriver_types.h> +#include <libetpan/generic_cache_types.h> +#include <libetpan/mailstorage_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct db_session_state_data { + char db_filename[PATH_MAX]; + struct mail_flags_store * db_flags_store; +}; + +/* db storage */ + +/* + db_mailstorage is the state data specific to the db storage. + + - pathname is the path of the db storage. +*/ + +struct db_mailstorage { + char * db_pathname; +}; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbstorage.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbstorage.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,156 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbstorage.c,v 1.6 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "dbstorage.h" +#include "mailstorage.h" + +#include "mail.h" +#include "mailmessage.h" +#include "dbdriver.h" +#include "maildriver.h" + +#include <stdlib.h> +#include <string.h> + +/* db storage */ + +static int db_mailstorage_connect(struct mailstorage * storage); +static int +db_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void db_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver db_mailstorage_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sto_name */ "db", + /* sto_connect */ db_mailstorage_connect, + /* sto_get_folder_session */ db_mailstorage_get_folder_session, + /* sto_uninitialize */ db_mailstorage_uninitialize, +#else + .sto_name = "db", + .sto_connect = db_mailstorage_connect, + .sto_get_folder_session = db_mailstorage_get_folder_session, + .sto_uninitialize = db_mailstorage_uninitialize, +#endif +}; + +LIBETPAN_EXPORT +int db_mailstorage_init(struct mailstorage * storage, + char * db_pathname) +{ + struct db_mailstorage * db_storage; + + db_storage = malloc(sizeof(* db_storage)); + if (db_storage == NULL) + goto err; + + db_storage->db_pathname = strdup(db_pathname); + if (db_storage->db_pathname == NULL) + goto free; + + storage->sto_data = db_storage; + storage->sto_driver = &db_mailstorage_driver; + + return MAIL_NO_ERROR; + + free: + free(db_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void db_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct db_mailstorage * db_storage; + + db_storage = storage->sto_data; + free(db_storage->db_pathname); + free(db_storage); + + storage->sto_data = NULL; +} + +static int db_mailstorage_connect(struct mailstorage * storage) +{ + struct db_mailstorage * db_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + db_storage = storage->sto_data; + + driver = db_session_driver; + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailsession_connect_path(session, db_storage->db_pathname); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int +db_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} + Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbstorage.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/db/dbstorage.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: dbstorage.h,v 1.3 2005/06/01 12:21:57 smarinier Exp $ + */ + +#ifndef DBSTORAGE_H + +#define DBSTORAGE_H + +#include <libetpan/dbdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + db_mailstorage_init is the constructor for a DB storage. + + @param storage this is the storage to initialize. + + @param pathname is the directory that contains the mailbox. +*/ + +LIBETPAN_EXPORT +int db_mailstorage_init(struct mailstorage * storage, + char * db_pathname); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/hotmail/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/hotmail/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/hotmail/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/hotmail/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,16 @@ +top_builddir = ../../../.. + +HEADERS = \ + hotmailstorage.h + + +SOURCES = \ + hotmailstorage.c + + +TARGET = libhotmail +INCLUDES = -I../../interface \ + -I../pop3 + + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/hotmail/hotmailstorage.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/hotmail/hotmailstorage.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,67 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: hotmailstorage.c,v 1.4 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "hotmailstorage.h" + +#include "pop3storage.h" +#include "pop3driver_types.h" + +/* + hotway is a gateway from hotmail to POP3 + + http://hotwayd.sourceforge.net/ +*/ + +static char hotway_command[512] = "/usr/bin/hotwayd"; + +LIBETPAN_EXPORT +int hotmail_mailstorage_init(struct mailstorage * storage, + char * hotmail_login, char * hotmail_password, + int hotmail_cached, char * hotmail_cache_directory, + char * hotmail_flags_directory) +{ + return pop3_mailstorage_init(storage, + "hotmail.dummy", 0, + hotway_command, + CONNECTION_TYPE_COMMAND, POP3_AUTH_TYPE_PLAIN, + hotmail_login, hotmail_password, + hotmail_cached, hotmail_cache_directory, + hotmail_flags_directory); +} + Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/hotmail/hotmailstorage.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/hotmail/hotmailstorage.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,57 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: hotmailstorage.h,v 1.3 2005/06/01 12:21:58 smarinier Exp $ + */ + +#ifndef HOTMAILSTORAGE_H + +#define HOTMAILSTORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailstorage_types.h" + +LIBETPAN_EXPORT +int hotmail_mailstorage_init(struct mailstorage * storage, + char * hotmail_login, char * hotmail_password, + int hotmail_cached, char * hotmail_cache_directory, + char * hotmail_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif + Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,30 @@ +top_builddir = ../../../.. + +HEADERS = \ + imapdriver.h \ + imapdriver_message.h \ + imapdriver_cached.h \ + imapdriver_cached_message.h \ + imapdriver_types.h \ + imapstorage.h + + +SOURCES = \ + imapdriver.c \ + imapdriver_cached.c \ + imapdriver_cached_message.c \ + imapdriver_message.c \ + imapdriver_tools.c \ + imapstorage.c + + +TARGET = libimap +INCLUDES = -I../../interface \ + -I../../tools \ + -I$(srcdir)/low-level/imap \ + -I$(srcdir)/low-level/mime \ + -I$(srcdir)/low-level/imf \ + -I$(srcdir)/data-types + + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1335 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver.c,v 1.55 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "imapdriver.h" + +#include "mail.h" +#include "imapdriver_tools.h" +#include "mailmessage.h" +#include "imapdriver_message.h" +#include "imapdriver_types.h" +#include "maildriver.h" +#include "maildriver_tools.h" +#include "generic_cache.h" + +#include <stdlib.h> +#include <string.h> + +static int imapdriver_initialize(mailsession * session); + +static void imapdriver_uninitialize(mailsession * session); + +static int imapdriver_connect_stream(mailsession * session, mailstream * s); + +static int imapdriver_starttls(mailsession * session); + +static int imapdriver_login(mailsession * session, + const char * userid, const char * password); + +static int imapdriver_logout(mailsession * session); + +static int imapdriver_noop(mailsession * session); + +static int imapdriver_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result); + +static int imapdriver_create_folder(mailsession * session, const char * mb); + +static int imapdriver_delete_folder(mailsession * session, const char * mb); + +static int imapdriver_rename_folder(mailsession * session, const char * mb, + const char * new_name); + +static int imapdriver_check_folder(mailsession * session); + +static int imapdriver_examine_folder(mailsession * session, const char * mb); + +static int imapdriver_select_folder(mailsession * session, const char * mb); +static int imapdriver_expunge_folder(mailsession * session); + +static int imapdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int imapdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int imapdriver_recent_number(mailsession * session, const char * mb, + uint32_t * result); + +static int imapdriver_unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +static int imapdriver_list_folders(mailsession * session, const char * mb, + struct mail_list ** result); +static int imapdriver_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result); +static int imapdriver_subscribe_folder(mailsession * session, const char * mb); +static int imapdriver_unsubscribe_folder(mailsession * session, const char * mb); +static int imapdriver_append_message(mailsession * session, + const char * message, size_t size); +static int imapdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); +static int imapdriver_copy_message(mailsession * session, + uint32_t num, const char * mb); + +static int imapdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +imapdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + + +#if 0 +static int imapdriver_search_messages(mailsession * session, const char * charset, + struct mail_search_key * key, + struct mail_search_result ** result); +#endif + +static int imapdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int imapdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static int imapdriver_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +static int imapdriver_remove_message(mailsession * session, uint32_t num); + +static mailsession_driver local_imap_session_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sess_name */ "imap", + + /* sess_initialize */ imapdriver_initialize, + /* sess_uninitialize */ imapdriver_uninitialize, + + /* sess_parameters */ NULL, + + /* sess_connect_stream */ imapdriver_connect_stream, + /* sess_connect_path */ NULL, + /* sess_starttls */ imapdriver_starttls, + /* sess_login */ imapdriver_login, + /* sess_logout */ imapdriver_logout, + /* sess_noop */ imapdriver_noop, + + /* sess_build_folder_name */ imapdriver_build_folder_name, + /* sess_create_folder */ imapdriver_create_folder, + /* sess_delete_folder */ imapdriver_delete_folder, + /* sess_rename_folder */ imapdriver_rename_folder, + /* sess_check_folder */ imapdriver_check_folder, + /* sess_examine_folder */ imapdriver_examine_folder, + /* sess_select_folder */ imapdriver_select_folder, + /* sess_expunge_folder */ imapdriver_expunge_folder, + /* sess_status_folder */ imapdriver_status_folder, + /* sess_messages_number */ imapdriver_messages_number, + /* sess_recent_number */ imapdriver_recent_number, + /* sess_unseen_number */ imapdriver_unseen_number, + /* sess_list_folders */ imapdriver_list_folders, + /* sess_lsub_folders */ imapdriver_lsub_folders, + /* sess_subscribe_folder */ imapdriver_subscribe_folder, + /* sess_unsubscribe_folder */ imapdriver_unsubscribe_folder, + + /* sess_append_message */ imapdriver_append_message, + /* sess_append_message_flags */ imapdriver_append_message_flags, + /* sess_copy_message */ imapdriver_copy_message, + /* sess_move_message */ NULL, + + /* sess_get_message */ imapdriver_get_message, + /* sess_get_message_by_uid */ imapdriver_get_message_by_uid, + + /* sess_get_messages_list */ imapdriver_get_messages_list, + /* sess_get_envelopes_list */ imapdriver_get_envelopes_list, + /* sess_remove_message */ imapdriver_remove_message, +#if 0 + /* sess_search_messages */ imapdriver_search_messages, +#endif + /* sess_login_sasl */ imapdriver_login_sasl, + +#else + .sess_name = "imap", + + .sess_initialize = imapdriver_initialize, + .sess_uninitialize = imapdriver_uninitialize, + + .sess_parameters = NULL, + + .sess_connect_stream = imapdriver_connect_stream, + .sess_connect_path = NULL, + .sess_starttls = imapdriver_starttls, + .sess_login = imapdriver_login, + .sess_logout = imapdriver_logout, + .sess_noop = imapdriver_noop, + + .sess_build_folder_name = imapdriver_build_folder_name, + .sess_create_folder = imapdriver_create_folder, + .sess_delete_folder = imapdriver_delete_folder, + .sess_rename_folder = imapdriver_rename_folder, + .sess_check_folder = imapdriver_check_folder, + .sess_examine_folder = imapdriver_examine_folder, + .sess_select_folder = imapdriver_select_folder, + .sess_expunge_folder = imapdriver_expunge_folder, + .sess_status_folder = imapdriver_status_folder, + .sess_messages_number = imapdriver_messages_number, + .sess_recent_number = imapdriver_recent_number, + .sess_unseen_number = imapdriver_unseen_number, + .sess_list_folders = imapdriver_list_folders, + .sess_lsub_folders = imapdriver_lsub_folders, + .sess_subscribe_folder = imapdriver_subscribe_folder, + .sess_unsubscribe_folder = imapdriver_unsubscribe_folder, + + .sess_append_message = imapdriver_append_message, + .sess_append_message_flags = imapdriver_append_message_flags, + .sess_copy_message = imapdriver_copy_message, + .sess_move_message = NULL, + + .sess_get_messages_list = imapdriver_get_messages_list, + .sess_get_envelopes_list = imapdriver_get_envelopes_list, + .sess_remove_message = imapdriver_remove_message, +#if 0 + .sess_search_messages = imapdriver_search_messages, +#endif + + .sess_get_message = imapdriver_get_message, + .sess_get_message_by_uid = imapdriver_get_message_by_uid, + .sess_login_sasl = imapdriver_login_sasl, +#endif +}; + +mailsession_driver * imap_session_driver = &local_imap_session_driver; + +static inline struct imap_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static mailimap * get_imap_session(mailsession * session) +{ + return get_data(session)->imap_session; +} + +static int imapdriver_initialize(mailsession * session) +{ + struct imap_session_state_data * data; + mailimap * imap; + struct mail_flags_store * flags_store; + + imap = mailimap_new(0, NULL); + if (imap == NULL) + goto err; + + flags_store = mail_flags_store_new(); + if (flags_store == NULL) + goto free_session; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto free_flags_store; + + data->imap_mailbox = NULL; + data->imap_session = imap; + data->imap_flags_store = flags_store; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_flags_store: + mail_flags_store_free(flags_store); + free_session: + mailimap_free(imap); + err: + return MAIL_ERROR_MEMORY; +} + +static void imap_flags_store_process(mailimap * imap, + struct mail_flags_store * flags_store) +{ + unsigned int i; + int r; + mailmessage * first; + mailmessage * last; + + mail_flags_store_sort(flags_store); + + if (carray_count(flags_store->fls_tab) == 0) + return; + + first = carray_get(flags_store->fls_tab, 0); + last = first; + + for(i = 1 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + if (last->msg_index + 1 == msg->msg_index) { + r = mail_flags_compare(first->msg_flags, msg->msg_flags); + if (r == 0) { + last = msg; + continue; + } + } + + r = imap_store_flags(imap, first->msg_index, + last->msg_index, first->msg_flags); + + first = msg; + last = msg; + } + + r = imap_store_flags(imap, first->msg_index, last->msg_index, + first->msg_flags); + + mail_flags_store_clear(flags_store); +} + +static void imapdriver_uninitialize(mailsession * session) +{ + struct imap_session_state_data * data; + + data = get_data(session); + + imap_flags_store_process(data->imap_session, + data->imap_flags_store); + mail_flags_store_free(data->imap_flags_store); + + mailimap_free(data->imap_session); + if (data->imap_mailbox != NULL) + free(data->imap_mailbox); + free(data); + + session->sess_data = NULL; +} + +static int imapdriver_connect_stream(mailsession * session, mailstream * s) +{ + int r; + + r = mailimap_connect(get_imap_session(session), s); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_login(mailsession * session, + const char * userid, const char * password) +{ + int r; + + r = mailimap_login(get_imap_session(session), userid, password); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_logout(mailsession * session) +{ + int r; + + imap_flags_store_process(get_imap_session(session), + get_data(session)->imap_flags_store); + + r = mailimap_logout(get_imap_session(session)); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_noop(mailsession * session) +{ + int r; + + r = mailimap_noop(get_imap_session(session)); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result) +{ + char delimiter[2] = "X"; + char * folder_name; + mailimap * imap; + struct mailimap_mailbox_list * mb_list; + int r; + clist * imap_list; + + imap = get_imap_session(session); + + r = mailimap_list(imap, mb, "", &imap_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (clist_begin(imap_list) == NULL) + return MAIL_ERROR_LIST; + + mb_list = clist_begin(imap_list)->data; + delimiter[0] = mb_list->mb_delimiter; + + folder_name = malloc(strlen(mb) + strlen(delimiter) + strlen(name) + 1); + if (folder_name == NULL) + return MAIL_ERROR_MEMORY; + + strcpy(folder_name, mb); + strcat(folder_name, delimiter); + strcat(folder_name, name); + + * result = folder_name; + + return MAIL_NO_ERROR; +} + +/* folders operations */ + +static int imapdriver_create_folder(mailsession * session, const char * mb) +{ + int r; + + r = mailimap_create(get_imap_session(session), mb); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_delete_folder(mailsession * session, const char * mb) +{ + int r; + + r = mailimap_delete(get_imap_session(session), mb); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_rename_folder(mailsession * session, const char * mb, + const char * new_name) +{ + int r; + + r = mailimap_rename(get_imap_session(session), mb, new_name); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_check_folder(mailsession * session) +{ + int r; + + imap_flags_store_process(get_imap_session(session), + get_data(session)->imap_flags_store); + + r = mailimap_check(get_imap_session(session)); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_examine_folder(mailsession * session, const char * mb) +{ + int r; + + r = mailimap_examine(get_imap_session(session), mb); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_select_folder(mailsession * session, const char * mb) +{ + int r; + char * new_mb; + char * old_mb; + + old_mb = get_data(session)->imap_mailbox; + if (old_mb != NULL) + if (strcmp(mb, old_mb) == 0) + return MAIL_NO_ERROR; + + imap_flags_store_process(get_imap_session(session), + get_data(session)->imap_flags_store); + + r = mailimap_select(get_imap_session(session), mb); + + switch (r) { + case MAILIMAP_NO_ERROR: + new_mb = strdup(mb); + if (new_mb == NULL) { + if (old_mb != NULL) + free(old_mb); + get_data(session)->imap_mailbox = NULL; + return MAIL_ERROR_MEMORY; + } + + get_data(session)->imap_mailbox = new_mb; + + return MAIL_NO_ERROR; + default: + return imap_error_to_mail_error(r); + } +} + +static int imapdriver_expunge_folder(mailsession * session) +{ + int r; + + imap_flags_store_process(get_imap_session(session), + get_data(session)->imap_flags_store); + + r = mailimap_expunge(get_imap_session(session)); + + return imap_error_to_mail_error(r); +} + +static int status_selected_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int r; + int res; + mailimap * imap; + uint32_t exists; + uint32_t unseen; + uint32_t recent; + struct mailimap_search_key * search_key; + clist * search_result; + + imap = get_imap_session(session); + + exists = imap->imap_selection_info->sel_exists; + recent = imap->imap_selection_info->sel_recent; + + search_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNSEEN, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, NULL, NULL); + if (search_key == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + /* default : use the RECENT count if search fails */ + unseen = recent; + r = mailimap_search(imap, NULL, search_key, &search_result); + mailimap_search_key_free(search_key); + if (r == MAILIMAP_NO_ERROR) { + /* if this succeed, we use the real count */ + unseen = clist_count(search_result); + mailimap_mailbox_data_search_free(search_result); + } + + * result_messages = exists; + * result_unseen = unseen; + * result_recent = recent; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int status_unselected_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + struct mailimap_status_att_list * att_list; + struct mailimap_mailbox_data_status * status; + int r; + int res; + clistiter * cur; + mailimap * imap; + + imap = get_imap_session(session); + + att_list = mailimap_status_att_list_new_empty(); + if (att_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_MESSAGES); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_RECENT); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_UNSEEN); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = mailimap_status(imap, mb, att_list, &status); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + res = imap_error_to_mail_error(r); + goto free; + } + + * result_messages = 0; + * result_recent = 0; + * result_unseen = 0; + + for (cur = clist_begin(status->st_info_list); + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_status_info * status_info; + + status_info = clist_content(cur); + switch (status_info->st_att) { + case MAILIMAP_STATUS_ATT_MESSAGES: + * result_messages = status_info->st_value; + break; + case MAILIMAP_STATUS_ATT_RECENT: + * result_recent = status_info->st_value; + break; + case MAILIMAP_STATUS_ATT_UNSEEN: + * result_unseen = status_info->st_value; + break; + } + } + + mailimap_mailbox_data_status_free(status); + mailimap_status_att_list_free(att_list); + + return MAIL_NO_ERROR; + + free: + mailimap_status_att_list_free(att_list); + err: + return res; +} + +static int imapdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int res; + int current_folder; + char * current_mb; + + if (mb == NULL) { + mb = get_data(session)->imap_mailbox; + if (mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + } + + current_mb = get_data(session)->imap_mailbox; + if (strcmp(mb, current_mb) == 0) + current_folder = 1; + else + current_folder = 0; + + if (current_folder) + return status_selected_folder(session, mb, result_messages, + result_recent, result_unseen); + else + return status_unselected_folder(session, mb, result_messages, + result_recent, result_unseen); + + err: + return res; +} + +/* TODO : more efficient functions */ + +static int imapdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = messages; + + return MAIL_NO_ERROR; +} + +static int imapdriver_recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + +static int imapdriver_unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +enum { + IMAP_LIST, IMAP_LSUB +}; + +static int imapdriver_list_lsub_folders(mailsession * session, int type, + const char * mb, + struct mail_list ** result) +{ + clist * imap_list; + struct mail_list * resp; + int r; + int res; + + switch (type) { + case IMAP_LIST: + r = mailimap_list(get_imap_session(session), mb, + "*", &imap_list); + break; + case IMAP_LSUB: + r = mailimap_lsub(get_imap_session(session), mb, + "*", &imap_list); + break; + default: + res = MAIL_ERROR_LIST; + goto err; + } + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + res = imap_error_to_mail_error(r); + goto err; + } + + r = imap_list_to_list(imap_list, &resp); + if (r != MAIL_NO_ERROR) { + mailimap_list_result_free(imap_list); + res = r; + goto err; + } + + mailimap_list_result_free(imap_list); + + * result = resp; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int imapdriver_list_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + return imapdriver_list_lsub_folders(session, IMAP_LIST, mb, + result); +} + +static int imapdriver_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + return imapdriver_list_lsub_folders(session, IMAP_LSUB, mb, + result); +} + +static int imapdriver_subscribe_folder(mailsession * session, const char * mb) +{ + int r; + + r = mailimap_subscribe(get_imap_session(session), mb); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_unsubscribe_folder(mailsession * session, const char * mb) +{ + int r; + + r = mailimap_unsubscribe(get_imap_session(session), mb); + + return imap_error_to_mail_error(r); +} + +/* messages operations */ + +static int imapdriver_append_message(mailsession * session, + const char * message, size_t size) +{ + int r; + + r = mailimap_append_simple(get_imap_session(session), + get_data(session)->imap_mailbox, + message, size); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + struct mailimap_flag_list * flag_list; + int r; + + if (flags != NULL) { + r = imap_flags_to_imap_flags(flags, &flag_list); + if (r != MAIL_NO_ERROR) + return r; + } + else { + flag_list = NULL; + } + + r = mailimap_append(get_imap_session(session), + get_data(session)->imap_mailbox, + flag_list, NULL, message, size); + + if (flag_list != NULL) + mailimap_flag_list_free(flag_list); + + return imap_error_to_mail_error(r); +} + +static int imapdriver_copy_message(mailsession * session, + uint32_t num, const char * mb) +{ + int r; + struct mailimap_set * set; + int res; + + set = mailimap_set_new_single(num); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailimap_uid_copy(get_imap_session(session), set, mb); + + mailimap_set_free(set); + + return imap_error_to_mail_error(r); + + err: + return res; +} + +static int imapdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + return imap_get_messages_list(get_imap_session(session), + session, imap_message_driver, 1, + result); +} + + + +#define IMAP_SET_MAX_COUNT 100 + +static int +imapdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + int res; + clist * fetch_result; + int r; + uint32_t exists; + clist * msg_list; + clistiter * set_iter; + + if (get_imap_session(session)->imap_selection_info == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + imap_flags_store_process(get_imap_session(session), + get_data(session)->imap_flags_store); + + exists = get_imap_session(session)->imap_selection_info->sel_exists; + + if (exists == 0) + return MAIL_NO_ERROR; + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + fetch_att = mailimap_fetch_att_new_flags(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = imap_add_envelope_fetch_att(fetch_type); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_fetch_type; + } + + r = maildriver_env_list_to_msg_list(env_list, &msg_list); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + if (clist_begin(msg_list) == NULL) { + /* no need to fetch envelopes */ + + mailimap_fetch_type_free(fetch_type); + clist_free(msg_list); + return MAIL_NO_ERROR; + } + + r = msg_list_to_imap_set(msg_list, &set); + if (r != MAIL_NO_ERROR) { + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + + set_iter = clist_begin(set->set_list); + while (set_iter != NULL) { + struct mailimap_set * subset; + unsigned int count; + + subset = mailimap_set_new_empty(); + if (subset == NULL) { + res = MAIL_ERROR_MEMORY; + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + res = MAIL_ERROR_MEMORY; + goto err; + } + + count = 0; + while (count < IMAP_SET_MAX_COUNT) { + struct mailimap_set_item * item; + + item = clist_content(set_iter); + set_iter = clist_delete(set->set_list, set_iter); + + r = mailimap_set_add(subset, item); + if (r != MAILIMAP_NO_ERROR) { + mailimap_set_item_free(item); + mailimap_set_free(subset); + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + res = MAIL_ERROR_MEMORY; + goto err; + } + + count ++; + + if (set_iter == NULL) + break; + } + + r = mailimap_uid_fetch(get_imap_session(session), subset, + fetch_type, &fetch_result); + + mailimap_set_free(subset); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + return imap_error_to_mail_error(r); + } + + if (clist_begin(fetch_result) == NULL) { + res = MAIL_ERROR_FETCH; + goto err; + } + + r = imap_fetch_result_to_envelop_list(fetch_result, env_list); + mailimap_fetch_list_free(fetch_result); + + if (r != MAIL_NO_ERROR) { + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + res = MAIL_ERROR_MEMORY; + goto err; + } + } + +#if 0 + r = mailimap_uid_fetch(get_imap_session(session), set, + fetch_type, &fetch_result); +#endif + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); +#if 0 + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + r = imap_fetch_result_to_envelop_list(fetch_result, env_list); + mailimap_fetch_list_free(fetch_result); + + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto err; + } +#endif + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + err: + return res; +} + + +#if 0 +static int imapdriver_search_messages(mailsession * session, const char * charset, + struct mail_search_key * key, + struct mail_search_result ** result) +{ + struct mailimap_search_key * imap_key; + int r; + clist * imap_result; + clist * result_list; + struct mail_search_result * search_result; + clistiter * cur; + + r = mail_search_to_imap_search(key, &imap_key); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_MEMORY; + + r = mailimap_uid_search(get_imap_session(session), charset, imap_key, + &imap_result); + + mailimap_search_key_free(imap_key); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + result_list = clist_new(); + if (result_list == NULL) + return MAIL_ERROR_MEMORY; + + for(cur = clist_begin(imap_result) ; cur != NULL ; cur = clist_next(cur)) { + uint32_t val = * (uint32_t *) clist_content(cur); + uint32_t * new; + + new = malloc(sizeof(* new)); + if (new == NULL) { + goto free_imap_result; + } + + * new = val; + + r = clist_append(result_list, new); + if (r != 0) { + free(new); + goto free_imap_result; + } + } + + search_result = mail_search_result_new(result_list); + if (search_result == NULL) + goto free_imap_result; + + mailimap_search_result_free(imap_result); + + * result = search_result; + + return MAIL_NO_ERROR; + + free_imap_result: + mailimap_search_result_free(imap_result); + return MAIL_ERROR_MEMORY; +} +#endif + +static int imapdriver_starttls(mailsession * session) +{ + mailimap * imap; + int r; + struct mailimap_capability_data * cap_data; + clistiter * cur; + int starttls; + int fd; + mailstream_low * low; + mailstream_low * new_low; + int capability_available; + + imap = get_imap_session(session); + + capability_available = FALSE; + if (imap->imap_connection_info != NULL) + if (imap->imap_connection_info->imap_capability != NULL) { + capability_available = TRUE; + cap_data = imap->imap_connection_info->imap_capability; + } + + if (!capability_available) { + r = mailimap_capability(imap, &cap_data); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + } + + starttls = FALSE; + for(cur = clist_begin(cap_data->cap_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_capability * cap; + + cap = clist_content(cur); + + if (cap->cap_type == MAILIMAP_CAPABILITY_NAME) + if (strcasecmp(cap->cap_data.cap_name, "STARTTLS") == 0) { + starttls = TRUE; + break; + } + } + + if (!capability_available) + mailimap_capability_data_free(cap_data); + + if (!starttls) + return MAIL_ERROR_NO_TLS; + + r = mailimap_starttls(imap); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + low = mailstream_get_low(imap->imap_stream); + fd = mailstream_low_get_fd(low); + if (fd == -1) + return MAIL_ERROR_STREAM; + + new_low = mailstream_low_tls_open(fd); + if (new_low == NULL) + return MAIL_ERROR_STREAM; + + mailstream_low_free(low); + mailstream_set_low(imap->imap_stream, new_low); + + return MAIL_NO_ERROR; +} + +static int imapdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, imap_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +/* Retrieve a message by UID + + libEtPan! uid format for IMAP is "UIDVALIDITY-UID" + where UIDVALIDITY and UID are decimal representation of + respectively uidvalidity and uid numbers. + + Return value: + MAIL_ERROR_INVAL if uid is NULL or has an incorrect format. + MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found + MAIL_NO_ERROR if message was found. Result is in result +*/ + +static int imapdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t uidvalidity; + uint32_t num; + char * p1, * p2; + mailimap * imap; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + uidvalidity = strtoul(uid, &p1, 10); + if (p1 == uid || * p1 != '-') + return MAIL_ERROR_INVAL; + + p1++; + num = strtoul(p1, &p2, 10); + if (p2 == p1 || * p2 != '\0') + return MAIL_ERROR_INVAL; + + imap = get_imap_session(session); + if (imap->imap_selection_info->sel_uidvalidity != uidvalidity) + return MAIL_ERROR_MSG_NOT_FOUND; + + return imapdriver_get_message(session, num, result); +} + +static int imapdriver_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ + int r; + + r = mailimap_authenticate(get_imap_session(session), + auth_type, server_fqdn, local_ip_port, remote_ip_port, + login, auth_name, password, realm); + + return imap_error_to_mail_error(r); +} + + +static int imapdriver_remove_message(mailsession * session, uint32_t num) { + + int res; + struct mail_flags *flags = NULL; + + /* protection if SELECT folder not done */ + if (get_imap_session(session)->imap_selection_info == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + /* Deleted flag */ + if ((flags = mail_flags_new_empty()) == NULL) { res = MAIL_ERROR_MEMORY; goto err;} + flags->fl_flags = MAIL_FLAG_DELETED; + + /* STORE num \Deleted */ + /* EXPUNGE */ + if ((res = imap_store_flags(get_imap_session(session), num, num, flags)) == MAILIMAP_NO_ERROR) + res = mailimap_expunge(get_imap_session(session)); + res = imap_error_to_mail_error(res); + +err: + if (flags != NULL) mail_flags_free( flags); + return res; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver.h,v 1.12 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef IMAPDRIVER_H + +#define IMAPDRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/imapdriver_types.h> + +extern mailsession_driver * imap_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_cached.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_cached.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1598 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_cached.c,v 1.55 2006/08/05 02:34:06 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "imapdriver_cached.h" + +#include "libetpan-config.h" + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <stdlib.h> + +#include "mail.h" +#include "imapdriver_tools.h" +#include "mail_cache_db.h" +#include "mailmessage.h" +#include "imapdriver_cached_message.h" +#include "maildriver.h" +#include "imapdriver_types.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "maildriver_tools.h" +#include "imapdriver.h" + +static int imapdriver_cached_initialize(mailsession * session); +static void imapdriver_cached_uninitialize(mailsession * session); + +static int imapdriver_cached_parameters(mailsession * session, + int id, void * value); + +static int imapdriver_cached_connect_stream(mailsession * session, + mailstream * s); + +static int imapdriver_cached_starttls(mailsession * session); + +static int imapdriver_cached_login(mailsession * session, + const char * userid, const char * password); +static int imapdriver_cached_logout(mailsession * session); +static int imapdriver_cached_noop(mailsession * session); +static int imapdriver_cached_build_folder_name(mailsession * session, + const char * mb, + const char * name, char ** result); +static int imapdriver_cached_create_folder(mailsession * session, const char * mb); +static int imapdriver_cached_delete_folder(mailsession * session, const char * mb); +static int imapdriver_cached_rename_folder(mailsession * session, const char * mb, + const char * new_name); +static int imapdriver_cached_check_folder(mailsession * session); +static int imapdriver_cached_examine_folder(mailsession * session, + const char * mb); +static int imapdriver_cached_select_folder(mailsession * session, const char * mb); +static int imapdriver_cached_expunge_folder(mailsession * session); +static int imapdriver_cached_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen); +static int imapdriver_cached_messages_number(mailsession * session, + const char * mb, + uint32_t * result); +static int imapdriver_cached_recent_number(mailsession * session, const char * mb, + uint32_t * result); +static int imapdriver_cached_unseen_number(mailsession * session, const char * mb, + uint32_t * result); +static int imapdriver_cached_list_folders(mailsession * session, const char * mb, + struct mail_list ** result); +static int imapdriver_cached_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result); +static int imapdriver_cached_subscribe_folder(mailsession * session, + const char * mb); +static int imapdriver_cached_unsubscribe_folder(mailsession * session, + const char * mb); +static int imapdriver_cached_append_message(mailsession * session, + const char * message, size_t size); +static int imapdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); +static int imapdriver_cached_copy_message(mailsession * session, + uint32_t num, const char * mb); + +static int imapdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** + result); +static int +imapdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); +static int imapdriver_cached_remove_message(mailsession * session, + uint32_t num); + +#if 0 +static int imapdriver_cached_search_messages(mailsession * session, + const char * charset, + struct mail_search_key * key, + struct mail_search_result ** + result); +#endif + +static int imapdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int imapdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static int imapdriver_cached_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +static mailsession_driver local_imap_cached_session_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sess_name */ "imap-cached", + + /* sess_initialize */ imapdriver_cached_initialize, + /* sess_uninitialize */ imapdriver_cached_uninitialize, + + /* sess_parameters */ imapdriver_cached_parameters, + + /* sess_connect_stream */ imapdriver_cached_connect_stream, + /* sess_connect_path */ NULL, + /* sess_starttls */ imapdriver_cached_starttls, + /* sess_login */ imapdriver_cached_login, + /* sess_logout */ imapdriver_cached_logout, + /* sess_noop */ imapdriver_cached_noop, + + /* sess_build_folder_name */ imapdriver_cached_build_folder_name, + /* sess_create_folder */ imapdriver_cached_create_folder, + /* sess_delete_folder */ imapdriver_cached_delete_folder, + /* sess_rename_folder */ imapdriver_cached_rename_folder, + /* sess_check_folder */ imapdriver_cached_check_folder, + /* sess_examine_folder */ imapdriver_cached_examine_folder, + /* sess_select_folder */ imapdriver_cached_select_folder, + /* sess_expunge_folder */ imapdriver_cached_expunge_folder, + /* sess_status_folder */ imapdriver_cached_status_folder, + /* sess_messages_number */ imapdriver_cached_messages_number, + /* sess_recent_number */ imapdriver_cached_recent_number, + /* sess_unseen_number */ imapdriver_cached_unseen_number, + /* sess_list_folders */ imapdriver_cached_list_folders, + /* sess_lsub_folders */ imapdriver_cached_lsub_folders, + /* sess_subscribe_folder */ imapdriver_cached_subscribe_folder, + /* sess_unsubscribe_folder */ imapdriver_cached_unsubscribe_folder, + + /* sess_append_message */ imapdriver_cached_append_message, + /* sess_append_message_flags */ imapdriver_cached_append_message_flags, + /* sess_copy_message */ imapdriver_cached_copy_message, + /* sess_move_message */ NULL, + + /* sess_get_message */ imapdriver_cached_get_message, + /* sess_get_message_by_uid */ imapdriver_cached_get_message_by_uid, + + /* sess_get_messages_list */ imapdriver_cached_get_messages_list, + /* sess_get_envelopes_list */ imapdriver_cached_get_envelopes_list, + /* sess_remove_message */ imapdriver_cached_remove_message, +#if 0 + /* sess_search_messages */ imapdriver_cached_search_messages, +#endif + /* sess_cached_login_sasl */ imapdriver_cached_login_sasl, + +#else + .sess_name = "imap-cached", + + .sess_initialize = imapdriver_cached_initialize, + .sess_uninitialize = imapdriver_cached_uninitialize, + + .sess_parameters = imapdriver_cached_parameters, + + .sess_connect_stream = imapdriver_cached_connect_stream, + .sess_connect_path = NULL, + .sess_starttls = imapdriver_cached_starttls, + .sess_login = imapdriver_cached_login, + .sess_logout = imapdriver_cached_logout, + .sess_noop = imapdriver_cached_noop, + + .sess_build_folder_name = imapdriver_cached_build_folder_name, + .sess_create_folder = imapdriver_cached_create_folder, + .sess_delete_folder = imapdriver_cached_delete_folder, + .sess_rename_folder = imapdriver_cached_rename_folder, + .sess_check_folder = imapdriver_cached_check_folder, + .sess_examine_folder = imapdriver_cached_examine_folder, + .sess_select_folder = imapdriver_cached_select_folder, + .sess_expunge_folder = imapdriver_cached_expunge_folder, + .sess_status_folder = imapdriver_cached_status_folder, + .sess_messages_number = imapdriver_cached_messages_number, + .sess_recent_number = imapdriver_cached_recent_number, + .sess_unseen_number = imapdriver_cached_unseen_number, + .sess_list_folders = imapdriver_cached_list_folders, + .sess_lsub_folders = imapdriver_cached_lsub_folders, + .sess_subscribe_folder = imapdriver_cached_subscribe_folder, + .sess_unsubscribe_folder = imapdriver_cached_unsubscribe_folder, + + .sess_append_message = imapdriver_cached_append_message, + .sess_append_message_flags = imapdriver_cached_append_message_flags, + .sess_copy_message = imapdriver_cached_copy_message, + .sess_move_message = NULL, + + .sess_get_messages_list = imapdriver_cached_get_messages_list, + .sess_get_envelopes_list = imapdriver_cached_get_envelopes_list, + .sess_remove_message = imapdriver_cached_remove_message, +#if 0 + .sess_search_messages = imapdriver_cached_search_messages, +#endif + + .sess_get_message = imapdriver_cached_get_message, + .sess_get_message_by_uid = imapdriver_cached_get_message_by_uid, + .sess_login_sasl = imapdriver_cached_login_sasl, +#endif +}; + +mailsession_driver * imap_cached_session_driver = +&local_imap_cached_session_driver; + +#define CACHE_MESSAGE_LIST + +static inline struct imap_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * s) +{ + return get_cached_data(s)->imap_ancestor; +} + +static inline +struct imap_session_state_data * get_ancestor_data(mailsession * s) +{ + return get_ancestor(s)->sess_data; +} + +static inline mailimap * get_imap_session(mailsession * session) +{ + return get_ancestor_data(session)->imap_session; +} + +static int imapdriver_cached_initialize(mailsession * session) +{ + struct imap_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->imap_ancestor = mailsession_new(imap_session_driver); + if (data->imap_ancestor == NULL) + goto free_data; + data->imap_quoted_mb = NULL; + data->imap_cache_directory[0] = '\0'; + data->imap_uid_list = carray_new(128); + if (data->imap_uid_list == NULL) + goto free_session; + data->imap_uidvalidity = 0; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_session: + mailsession_free(data->imap_ancestor); + free_data: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void +free_quoted_mb(struct imap_cached_session_state_data * imap_cached_data) +{ + if (imap_cached_data->imap_quoted_mb != NULL) { + free(imap_cached_data->imap_quoted_mb); + imap_cached_data->imap_quoted_mb = NULL; + } +} + +struct uid_cache_item { + uint32_t uid; + uint32_t size; +}; + +static int update_uid_cache(mailsession * session, + struct mailmessage_list * env_list) +{ + unsigned int i; + int r; + struct imap_cached_session_state_data * data; + int res; + mailimap * imap; + + data = get_cached_data(session); + imap = get_imap_session(session); + + /* free all UID cache */ + for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { + struct uid_cache_item * cache_item; + + cache_item = carray_get(data->imap_uid_list, i); + free(cache_item); + } + + if (env_list == NULL) { + r = carray_set_size(data->imap_uid_list, 0); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + } + else { + /* build UID cache */ + r = carray_set_size(data->imap_uid_list, + carray_count(env_list->msg_tab)); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + struct uid_cache_item * cache_item; + mailmessage * msg; + + cache_item = malloc(sizeof(* cache_item)); + if (cache_item == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + msg = carray_get(env_list->msg_tab, i); + cache_item->uid = msg->msg_index; + cache_item->size = msg->msg_size; + + carray_set(data->imap_uid_list, i, cache_item); + } + } + data->imap_uidvalidity = imap->imap_selection_info->sel_uidvalidity; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static void check_for_uid_cache(mailsession * session) +{ +#if 0 + mailsession * imap; +#endif + mailimap * imap; +#if 0 + struct imap_session_state_data * imap_data; +#endif + clist * list; + clistiter * cur; + struct imap_cached_session_state_data * data; + unsigned int i; + unsigned dest; + + data = get_cached_data(session); +#if 0 + imap = get_ancestor(session); + + imap_data = imap->data; +#endif + + imap = get_imap_session(session); + + if (imap->imap_response_info == NULL) + return; + + list = imap->imap_response_info->rsp_expunged; + if (list == NULL) + return; + + dest = 0; + i = 0; + /* remove expunged */ + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + uint32_t expunged; + + expunged = * (uint32_t *) clist_content(cur); + + while (i < carray_count(data->imap_uid_list)) { + struct uid_cache_item * cache_item; + + if (dest + 1 == expunged) { + cache_item = carray_get(data->imap_uid_list, i); + free(cache_item); + i ++; + break; + } + else { + cache_item = carray_get(data->imap_uid_list, i); + carray_set(data->imap_uid_list, dest, cache_item); + i ++; + dest ++; + } + } + } + /* complete list */ + while (i < carray_count(data->imap_uid_list)) { + struct uid_cache_item * cache_item; + + cache_item = carray_get(data->imap_uid_list, i); + carray_set(data->imap_uid_list, dest, cache_item); + i ++; + dest ++; + } + carray_set_size(data->imap_uid_list, dest); +} + +static void imapdriver_cached_uninitialize(mailsession * session) +{ + struct imap_cached_session_state_data * data; + unsigned int i; + + data = get_cached_data(session); + + for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { + struct uid_cache_item * cache_item; + + cache_item = carray_get(data->imap_uid_list, i); + free(cache_item); + } + carray_free(data->imap_uid_list); + free_quoted_mb(data); + mailsession_free(data->imap_ancestor); + free(data); + + session->sess_data = NULL; +} + + +static int imapdriver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct imap_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + switch (id) { + case IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(data->imap_cache_directory, value, PATH_MAX); + data->imap_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->imap_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + } + + return MAIL_ERROR_INVAL; +} + + +static int imapdriver_cached_connect_stream(mailsession * session, + mailstream * s) +{ + int r; + + check_for_uid_cache(session); + + r = mailsession_connect_stream(get_ancestor(session), s); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_starttls(mailsession * session) +{ + int r; + + r = mailsession_starttls(get_ancestor(session)); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_login(mailsession * session, + const char * userid, const char * password) +{ + int r; + + r = mailsession_login(get_ancestor(session), userid, password); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_logout(mailsession * session) +{ + int r; + + r = mailsession_logout(get_ancestor(session)); + + check_for_uid_cache(session); + + if (r == MAIL_NO_ERROR) { + struct imap_cached_session_state_data * imap_cached_data; + + imap_cached_data = get_cached_data(session); + + free_quoted_mb(imap_cached_data); + } + + return r; +} + +static int imapdriver_cached_noop(mailsession * session) +{ + int r; + + r = mailsession_noop(get_ancestor(session)); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_build_folder_name(mailsession * session, + const char * mb, + const char * name, char ** result) +{ + int r; + + r = mailsession_build_folder_name(get_ancestor(session), mb, + name, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_create_folder(mailsession * session, const char * mb) +{ + int r; + + r = mailsession_create_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_delete_folder(mailsession * session, const char * mb) +{ + int r; + + r = mailsession_delete_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_rename_folder(mailsession * session, const char * mb, + const char * new_name) +{ + int r; + + r = mailsession_rename_folder(get_ancestor(session), mb, new_name); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_check_folder(mailsession * session) +{ + int r; + + r = mailsession_check_folder(get_ancestor(session)); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_examine_folder(mailsession * session, + const char * mb) +{ + int r; + + r = mailsession_examine_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int get_cache_folder(mailsession * session, char ** result) +{ +#if 0 + mailsession * imap_session; +#endif + mailimap * imap; + char * mb; + char * cache_dir; + char * dirname; + char * quoted_mb; + int res; + int r; + char key[PATH_MAX]; +#if 0 + struct imap_session_state_data * imap_data; + struct imap_cached_session_state_data * cached_data; +#endif + +#if 0 + imap_session = get_ancestor(session); + imap_data = imap_session->data; + imap = imap_data->session; +#endif + imap = get_imap_session(session); + + mb = get_ancestor_data(session)->imap_mailbox; + + cache_dir = get_cached_data(session)->imap_cache_directory; + + if (imap->imap_state != MAILIMAP_STATE_SELECTED) + return MAIL_ERROR_BAD_STATE; + + if (imap->imap_selection_info == NULL) + return MAIL_ERROR_BAD_STATE; + + quoted_mb = maildriver_quote_mailbox(mb); + if (quoted_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(key, PATH_MAX, "%s/%s", cache_dir, quoted_mb); + + dirname = strdup(key); + if (dirname == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mb; + } + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_dirname; + } + + free(quoted_mb); + + * result = dirname; + + return MAIL_NO_ERROR; + + free_dirname: + free(dirname); + free_mb: + free(quoted_mb); + err: + return res; +} + +static int imapdriver_cached_select_folder(mailsession * session, const char * mb) +{ + int r; + char * quoted_mb; + struct imap_cached_session_state_data * data; + mailsession * imap; + char * old_mb; + + imap = get_ancestor(session); + + old_mb = get_ancestor_data(session)->imap_mailbox; + if (old_mb != NULL) + if (strcmp(mb, old_mb) == 0) + return MAIL_NO_ERROR; + + r = mailsession_select_folder(get_ancestor(session), mb); + if (r != MAIL_NO_ERROR) + return r; + + check_for_uid_cache(session); + + quoted_mb = NULL; + r = get_cache_folder(session, "ed_mb); + if (r != MAIL_NO_ERROR) + return r; + + data = get_cached_data(session); + if (data->imap_quoted_mb != NULL) + free(data->imap_quoted_mb); + data->imap_quoted_mb = quoted_mb; + + /* clear UID cache */ + carray_set_size(data->imap_uid_list, 0); + + return MAIL_NO_ERROR; +} + +static int imapdriver_cached_expunge_folder(mailsession * session) +{ + int r; + + r = mailsession_expunge_folder(get_ancestor(session)); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int r; + + r = mailsession_status_folder(get_ancestor(session), mb, result_messages, + result_recent, result_unseen); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_messages_number(mailsession * session, + const char * mb, + uint32_t * result) +{ + int r; + + r = mailsession_messages_number(get_ancestor(session), mb, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + int r; + + r = mailsession_recent_number(get_ancestor(session), mb, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + int r; + + r = mailsession_unseen_number(get_ancestor(session), mb, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_list_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + int r; + + r = mailsession_list_folders(get_ancestor(session), mb, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + int r; + + r = mailsession_lsub_folders(get_ancestor(session), mb, result); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_subscribe_folder(mailsession * session, + const char * mb) +{ + int r; + + r = mailsession_subscribe_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_unsubscribe_folder(mailsession * session, + const char * mb) +{ + int r; + + r = mailsession_unsubscribe_folder(get_ancestor(session), mb); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_append_message(mailsession * session, + const char * message, size_t size) +{ + int r; + + r = mailsession_append_message(get_ancestor(session), message, size); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + int r; + + r = mailsession_append_message_flags(get_ancestor(session), + message, size, flags); + + check_for_uid_cache(session); + + return r; +} + +static int imapdriver_cached_copy_message(mailsession * session, + uint32_t num, const char * mb) +{ + int r; + + r = mailsession_copy_message(get_ancestor(session), num, mb); + + check_for_uid_cache(session); + + return r; +} + +static int cmp_uid(uint32_t ** pa, uint32_t ** pb) +{ + uint32_t * a; + uint32_t * b; + + a = * pa; + b = * pb; + + return * a - * b; +} + + +static void get_uid_from_filename(char * filename) +{ + char * p; + + p = strstr(filename, "-part"); + if (p != NULL) + * p = 0; + p = strstr(filename, "-envelope"); + if (p != NULL) + * p = 0; + p = strstr(filename, "-rfc822"); + if (p != NULL) + * p = 0; +} + +#define ENV_NAME "env.db" + +static int boostrap_cache(mailsession * session) +{ + struct mail_cache_db * cache_db; + char filename[PATH_MAX]; + mailimap * imap; + struct imap_cached_session_state_data * data; + MMAPString * mmapstr; + int r; + int res; + chashiter * iter; + chash * keys; + chash * keys_uid; + + data = get_cached_data(session); + imap = get_imap_session(session); + + if (data->imap_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME); + + r = mail_cache_db_open_lock(filename, &cache_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + keys = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (keys == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + r = mail_cache_db_get_keys(cache_db, keys); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_keys; + } + + keys_uid = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (keys_uid == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_keys; + } + + for(iter = chash_begin(keys) ; iter != NULL ; iter = chash_next(keys, iter)) { + chashdatum key; + chashdatum value; + char msg_uid[PATH_MAX]; + + chash_key(iter, &key); + if (key.len >= sizeof(msg_uid)) { + strncpy(msg_uid, key.data, sizeof(msg_uid)); + msg_uid[sizeof(msg_uid) - 1] = 0; + } + else { + strncpy(msg_uid, key.data, key.len); + msg_uid[key.len] = 0; + } + + get_uid_from_filename(msg_uid); + key.data = msg_uid; + key.len = strlen(msg_uid) + 1; + value.data = NULL; + value.len = 0; + chash_set(keys_uid, &key, &value, NULL); + } + + for(iter = chash_begin(keys_uid) ; iter != NULL ; iter = chash_next(keys_uid, iter)) { + chashdatum key; + uint32_t uidvalidity; + uint32_t index; + char * uid; + char * p1, * p2; + struct uid_cache_item * cache_item; + + chash_key(iter, &key); + uid = key.data; + + uidvalidity = strtoul(uid, &p1, 10); + if (p1 == uid || * p1 != '-') + continue; + + data->imap_uidvalidity = uidvalidity; + + p1++; + index = strtoul(p1, &p2, 10); + if (p2 == p1 || * p2 != '\0') + continue; + + cache_item = malloc(sizeof(* cache_item)); + if (cache_item == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_keys_uid; + } + + cache_item->uid = index; + cache_item->size = 0; + + carray_add(data->imap_uid_list, cache_item, NULL); + } + + chash_free(keys_uid); + chash_free(keys); + + mail_cache_db_close_unlock(filename, cache_db); + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + free_keys_uid: + chash_free(keys_uid); + free_keys: + chash_free(keys); + close_db: + mail_cache_db_close_unlock(filename, cache_db); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + + +static int imapdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** + result) +{ + mailimap * imap; + uint32_t uid_max; + struct imap_cached_session_state_data * data; + struct mailmessage_list * env_list; + unsigned i; + int r; + int res; + carray * tab; + + data = get_cached_data(session); + imap = get_imap_session(session); + + uid_max = 0; + +#ifdef CACHE_MESSAGE_LIST + if (data->imap_uidvalidity == 0) { + boostrap_cache(session); + } + + if (imap->imap_selection_info->sel_uidvalidity != data->imap_uidvalidity) { + update_uid_cache(session, NULL); + } + + /* get UID max */ + uid_max = 0; + for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { + struct uid_cache_item * cache_item; + + cache_item = carray_get(data->imap_uid_list, i); + if (cache_item->uid > uid_max) + uid_max = cache_item->uid; + } +#endif + + r = imap_get_messages_list(imap, session, imap_cached_message_driver, + uid_max + 1, &env_list); + + check_for_uid_cache(session); + + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + +#ifdef CACHE_MESSAGE_LIST + /* remove unsollicited message */ + i = 0; + while (i < carray_count(env_list->msg_tab)) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + if (msg->msg_index < uid_max + 1) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + mailmessage_free(msg); + carray_delete(env_list->msg_tab, i); + } + else { + i ++; + } + } + + tab = carray_new(carray_count(env_list->msg_tab) + + carray_count(data->imap_uid_list)); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + carray_set_size(tab, + carray_count(env_list->msg_tab) + carray_count(data->imap_uid_list)); + + /* sort cached data before adding them to the list */ + qsort(carray_data(data->imap_uid_list), carray_count(data->imap_uid_list), + sizeof(* carray_data(data->imap_uid_list)), + (int (*)(const void *, const void *)) cmp_uid); + + /* adds cached UID */ + for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) { + struct uid_cache_item * cache_item; + mailmessage * msg; + + cache_item = carray_get(data->imap_uid_list, i); + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = mailmessage_init(msg, session, imap_cached_message_driver, + cache_item->uid, cache_item->size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto free; + } + + carray_set(tab, i, msg); + } + + /* adds new elements */ + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + carray_set(tab, carray_count(data->imap_uid_list) + i, msg); + } + + /* replace list of messages in env_list */ + carray_free(env_list->msg_tab); + env_list->msg_tab = tab; + + r = update_uid_cache(session, env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } +#endif + + * result = env_list; + + return MAIL_NO_ERROR; + + free: + mailmessage_list_free(env_list); + err: + return res; +} + +#define IMAP_SET_MAX_COUNT 100 + +static int get_flags_list(mailsession * session, + struct mailmessage_list * env_list) +{ + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + int res; + clist * fetch_result; + int r; + clist * msg_list; +#if 0 + struct imap_session_state_data * data; +#endif + unsigned i; + unsigned dest; + clistiter * set_iter; + +#if 0 + data = session->data; +#endif + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + fetch_att = mailimap_fetch_att_new_flags(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = maildriver_env_list_to_msg_list_no_flags(env_list, &msg_list); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + if (clist_begin(msg_list) == NULL) { + /* no need to fetch envelopes */ + + clist_free(msg_list); + mailimap_fetch_type_free(fetch_type); + return MAIL_NO_ERROR; + } + + r = msg_list_to_imap_set(msg_list, &set); + if (r != MAIL_NO_ERROR) { + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + + set_iter = clist_begin(set->set_list); + while (set_iter != NULL) { + struct mailimap_set * subset; + unsigned int count; + + subset = mailimap_set_new_empty(); + if (subset == NULL) { + res = MAIL_ERROR_MEMORY; + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + res = MAIL_ERROR_MEMORY; + goto err; + } + + count = 0; + while (count < IMAP_SET_MAX_COUNT) { + struct mailimap_set_item * item; + + item = clist_content(set_iter); + set_iter = clist_delete(set->set_list, set_iter); + + r = mailimap_set_add(subset, item); + if (r != MAILIMAP_NO_ERROR) { + mailimap_set_item_free(item); + mailimap_set_free(subset); + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + res = MAIL_ERROR_MEMORY; + goto err; + } + + count ++; + + if (set_iter == NULL) + break; + } + + r = mailimap_uid_fetch(get_imap_session(session), subset, + fetch_type, &fetch_result); + + mailimap_set_free(subset); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + return imap_error_to_mail_error(r); + } + +#if 0 + if (clist_begin(fetch_result) == NULL) { + res = MAIL_ERROR_FETCH; + goto err; + } +#endif + + r = imap_fetch_result_to_envelop_list(fetch_result, env_list); + mailimap_fetch_list_free(fetch_result); + + if (r != MAIL_NO_ERROR) { + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + res = MAIL_ERROR_MEMORY; + goto err; + } + } + +#if 0 + r = mailimap_uid_fetch(get_imap_session(session), set, + fetch_type, &fetch_result); +#endif + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + +#if 0 + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + r = imap_fetch_result_to_envelop_list(fetch_result, env_list); + mailimap_fetch_list_free(fetch_result); + + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto err; + } +#endif + + /* remove messages that don't have flags */ + i = 0; + dest = 0; + while (i < carray_count(env_list->msg_tab)) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + if (msg->msg_flags != NULL) { + carray_set(env_list->msg_tab, dest, msg); + dest ++; + } + else { + mailmessage_free(msg); + } + i ++; + } + carray_set_size(env_list->msg_tab, dest); + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + err: + return res; +} + + +static int +imapdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + int res; + uint32_t i; + struct imap_cached_session_state_data * data; + MMAPString * mmapstr; + struct mail_cache_db * cache_db; + char filename[PATH_MAX]; + + data = get_cached_data(session); + if (data->imap_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME); + + r = mail_cache_db_open_lock(filename, &cache_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = imapdriver_get_cached_envelope(cache_db, mmapstr, + session, msg, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + } + + mail_cache_db_close_unlock(filename, cache_db); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + + check_for_uid_cache(session); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = get_flags_list(session, env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + +#ifdef CACHE_MESSAGE_LIST + r = update_uid_cache(session, env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } +#endif + + /* must write cache */ + + r = mail_cache_db_open_lock(filename, &cache_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + r = imapdriver_write_cached_envelope(cache_db, mmapstr, + session, msg, msg->msg_fields); + } + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db, NULL, env_list); + + mail_cache_db_close_unlock(filename, cache_db); + mmap_string_free(mmapstr); + + /* remove cache files */ + + maildriver_message_cache_clean_up(data->imap_quoted_mb, env_list, + get_uid_from_filename); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int imapdriver_cached_remove_message(mailsession * session, + uint32_t num) +{ + int r; + + r = mailsession_remove_message(get_ancestor(session), num); + + check_for_uid_cache(session); + + return r; +} + +#if 0 +static int imapdriver_cached_search_messages(mailsession * session, + char * charset, + struct mail_search_key * key, + struct mail_search_result ** + result) +{ + int r; + + r = mailsession_search_messages(get_ancestor(session), charset, key, result); + + check_for_uid_cache(session); + + return r; +} +#endif + +static int imapdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, imap_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +/* Retrieve a message by UID + * libEtPan! uid format for IMAP is "UIDVALIDITY-UID" + * where UIDVALIDITY and UID are decimal representation of + * respectively uidvalidity and uid numbers. + * Return value: + * MAIL_ERROR_INVAL if uid is NULL or has an incorrect format. + * MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found + * MAIL_NO_ERROR if message was found. Result is in result + */ +static int imapdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t uidvalidity; + uint32_t num; + char * p1, * p2; + mailimap *imap; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + uidvalidity = strtoul(uid, &p1, 10); + if (p1 == uid || * p1 != '-') + return MAIL_ERROR_INVAL; + + p1++; + num = strtoul(p1, &p2, 10); + if (p2 == p1 || * p2 != '\0') + return MAIL_ERROR_INVAL; + + imap = get_imap_session(session); + if (imap->imap_selection_info->sel_uidvalidity != uidvalidity) + return MAIL_ERROR_MSG_NOT_FOUND; + + return imapdriver_cached_get_message(session, num, result); +} + +static int imapdriver_cached_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ + return mailsession_login_sasl(get_ancestor(session), auth_type, + server_fqdn, + local_ip_port, + remote_ip_port, + login, auth_name, + password, realm); +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_cached.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_cached.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_cached.h,v 1.11 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef IMAPDRIVER_CACHED_H + +#define IMAPDRIVER_CACHED_H + +#include <libetpan/imapdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * imap_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_cached_message.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_cached_message.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,693 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_cached_message.c,v 1.25 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "imapdriver_cached_message.h" + +#include "imapdriver_tools.h" +#include "imapdriver_message.h" +#include "imapdriver_cached.h" +#include "imapdriver_types.h" +#include "imapdriver.h" +#include "mailmessage.h" +#include "generic_cache.h" +#include "mail_cache_db.h" + +#include <string.h> +#include <stdlib.h> + +static int imap_initialize(mailmessage * msg_info); + +static void imap_uninitialize(mailmessage * msg_info); + +static void imap_flush(mailmessage * msg_info); + +static void imap_check(mailmessage * msg_info); + +static void imap_fetch_result_free(mailmessage * msg_info, + char * msg); + +static int imap_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int imap_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int imap_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + +static int imap_fetch_size(mailmessage * msg_info, + size_t * result); + +static int imap_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + +static int imap_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +static int imap_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +static int imap_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +static int imap_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + +static int imap_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + +static int imap_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static mailmessage_driver local_imap_cached_message_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* msg_name */ "imap-cached", + + /* msg_initialize */ imap_initialize, + /* msg_uninitialize */ imap_uninitialize, + + /* msg_flush */ imap_flush, + /* msg_check */ imap_check, + + /* msg_fetch_result_free */ imap_fetch_result_free, + + /* msg_fetch */ imap_fetch, + /* msg_fetch_header */ imap_fetch_header, + /* msg_fetch_body */ imap_fetch_body, + /* msg_fetch_size */ imap_fetch_size, + /* msg_get_bodystructure */ imap_get_bodystructure, + /* msg_fetch_section */ imap_fetch_section, + /* msg_fetch_section_header */ imap_fetch_section_header, + /* msg_fetch_section_mime */ imap_fetch_section_mime, + /* msg_fetch_section_body */ imap_fetch_section_body, + /* msg_fetch_envelope */ imap_fetch_envelope, + + /* msg_get_flags */ imap_get_flags, +#else + .msg_name = "imap-cached", + + .msg_initialize = imap_initialize, + .msg_uninitialize = imap_uninitialize, + + .msg_flush = imap_flush, + .msg_check = imap_check, + + .msg_fetch_result_free = imap_fetch_result_free, + + .msg_fetch = imap_fetch, + .msg_fetch_header = imap_fetch_header, + .msg_fetch_body = imap_fetch_body, + .msg_fetch_size = imap_fetch_size, + .msg_get_bodystructure = imap_get_bodystructure, + .msg_fetch_section = imap_fetch_section, + .msg_fetch_section_header = imap_fetch_section_header, + .msg_fetch_section_mime = imap_fetch_section_mime, + .msg_fetch_section_body = imap_fetch_section_body, + .msg_fetch_envelope = imap_fetch_envelope, + + .msg_get_flags = imap_get_flags, +#endif +}; + +mailmessage_driver * imap_cached_message_driver = +&local_imap_cached_message_driver; + +static inline struct imap_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailmessage * get_ancestor(mailmessage * msg_info) +{ + return msg_info->msg_data; +} + +static inline struct imap_cached_session_state_data * +cached_session_get_data(mailsession * s) +{ + return s->sess_data; +} + +static inline mailsession * cached_session_get_ancestor(mailsession * s) +{ + return cached_session_get_data(s)->imap_ancestor; +} + +static inline struct imap_session_state_data * +cached_session_get_ancestor_data(mailsession * s) +{ + return cached_session_get_ancestor(s)->sess_data; +} + +static inline mailimap * +cached_session_get_imap_session(mailsession * session) +{ + return cached_session_get_ancestor_data(session)->imap_session; +} + +static inline mailimap * get_imap_session(mailmessage * msg) +{ + return cached_session_get_imap_session(msg->msg_session); +} + +static inline mailsession * get_ancestor_session(mailmessage * msg_info) +{ + return cached_session_get_ancestor(msg_info->msg_session); +} + + +static void generate_key_from_mime_section(char * key, size_t size, + struct mailmime * mime) +{ + clistiter * cur; + MMAPString * gstr; + struct mailmime_section * part; + int r; + + snprintf(key, size, "unvalid"); + + r = mailmime_get_section_id(mime, &part); + if (r != MAILIMF_NO_ERROR) + goto err; + + gstr = mmap_string_new("part"); + if (gstr == NULL) + goto free_section; + + for(cur = clist_begin(part->sec_list) ; + cur != NULL ; cur = clist_next(cur)) { + char s[20]; + + snprintf(s, 20, ".%u", * (uint32_t *) clist_content(cur)); + if (mmap_string_append(gstr, s) == NULL) + goto free_str; + } + + snprintf(key, size, "%s", gstr->str); + + mmap_string_free(gstr); + mailmime_section_free(part); + + return; + + free_str: + mmap_string_free(gstr); + free_section: + mailmime_section_free(part); + err:; +} + +static void generate_key_from_section(char * key, size_t size, + mailmessage * msg_info, + struct mailmime * mime, int type) +{ + char section_str[PATH_MAX]; + + generate_key_from_mime_section(section_str, PATH_MAX, mime); + + switch (type) { + case IMAP_SECTION_MESSAGE: + snprintf(key, size, "%s-%s", msg_info->msg_uid, section_str); + break; + case IMAP_SECTION_HEADER: + snprintf(key, size, "%s-%s-header", msg_info->msg_uid, section_str); + break; + case IMAP_SECTION_MIME: + snprintf(key, size, "%s-%s-mime", msg_info->msg_uid, section_str); + break; + case IMAP_SECTION_BODY: + snprintf(key, size, "%s-%s-text", msg_info->msg_uid, section_str); + break; + } +} + +static void generate_key_from_message(char * key, size_t size, + mailmessage * msg_info, + int type) +{ + switch (type) { + case MAILIMAP_MSG_ATT_RFC822: + snprintf(key, size, "%s-rfc822", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_RFC822_HEADER: + snprintf(key, size, "%s-rfc822-header", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_RFC822_TEXT: + snprintf(key, size, "%s-rfc822-text", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_ENVELOPE: + snprintf(key, size, "%s-envelope", msg_info->msg_uid); + break; + } +} + +static void build_cache_name(char * filename, size_t size, + mailmessage * msg, char * key) +{ + char * quoted_mb; + + quoted_mb = get_cached_session_data(msg)->imap_quoted_mb; + + snprintf(filename, size, "%s/%s", quoted_mb, key); +} + +static int imap_initialize(mailmessage * msg_info) +{ + mailmessage * ancestor; + int r; + char key[PATH_MAX]; + char * uid; + mailimap * imap; + + ancestor = mailmessage_new(); + if (ancestor == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(ancestor, get_ancestor_session(msg_info), + imap_message_driver, + msg_info->msg_index, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(ancestor); + return r; + } + + imap = get_imap_session(msg_info); + + snprintf(key, PATH_MAX, "%u-%u", + imap->imap_selection_info->sel_uidvalidity, msg_info->msg_index); + uid = strdup(key); + if (uid == NULL) { + mailmessage_free(ancestor); + return MAIL_ERROR_MEMORY; + } + + msg_info->msg_data = ancestor; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + +static void imap_uninitialize(mailmessage * msg_info) +{ + mailmessage_free(get_ancestor(msg_info)); + msg_info->msg_data = NULL; +} + +static void imap_flush(mailmessage * msg_info) +{ + if (msg_info->msg_mime != NULL) { + mailmime_free(msg_info->msg_mime); + msg_info->msg_mime = NULL; + } +} + +static void imap_check(mailmessage * msg_info) +{ + get_ancestor(msg_info)->msg_flags = msg_info->msg_flags; + mailmessage_check(get_ancestor(msg_info)); + get_ancestor(msg_info)->msg_flags = NULL; +} + +static void imap_fetch_result_free(mailmessage * msg_info, + char * msg) +{ + mailmessage_fetch_result_free(get_ancestor(msg_info), msg); +} + +static int imap_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_message(key, PATH_MAX, + msg_info, MAILIMAP_MSG_ATT_RFC822); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch(get_ancestor(msg_info), + result, result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, strlen(* result)); + + return r; +} + +static int imap_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_message(key, PATH_MAX, + msg_info, MAILIMAP_MSG_ATT_RFC822_HEADER); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_header(get_ancestor(msg_info), result, + result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_message(key, PATH_MAX, + msg_info, MAILIMAP_MSG_ATT_RFC822_TEXT); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_body(get_ancestor(msg_info), result, + result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_fetch_size(mailmessage * msg_info, + size_t * result) +{ + return mailmessage_fetch_size(get_ancestor(msg_info), result); +} + +static int imap_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result) +{ + int r; + + if (msg_info->msg_mime != NULL) { + * result = msg_info->msg_mime; + + return MAIL_NO_ERROR; + } + + r = mailmessage_get_bodystructure(get_ancestor(msg_info), + result); + if (r == MAIL_NO_ERROR) { + msg_info->msg_mime = get_ancestor(msg_info)->msg_mime; + get_ancestor(msg_info)->msg_mime = NULL; + } + + return r; +} + +static int imap_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_section(key, PATH_MAX, + msg_info, mime, IMAP_SECTION_MESSAGE); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_section(get_ancestor(msg_info), + mime, result, result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_section(key, PATH_MAX, + msg_info, mime, IMAP_SECTION_HEADER); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_section_header(get_ancestor(msg_info), + mime, result, result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_section(key, PATH_MAX, + msg_info, mime, IMAP_SECTION_MIME); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_section_mime(get_ancestor(msg_info), + mime, result, result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + char key[PATH_MAX]; + char filename[PATH_MAX]; + int r; + char * str; + size_t len; + + generate_key_from_section(key, PATH_MAX, + msg_info, mime, IMAP_SECTION_BODY); + + build_cache_name(filename, PATH_MAX, msg_info, key); + + r = generic_cache_read(filename, &str, &len); + if (r == MAIL_NO_ERROR) { + + * result = str; + * result_len = len; + + return MAIL_NO_ERROR; + } + + r = mailmessage_fetch_section_body(get_ancestor(msg_info), + mime, result, result_len); + if (r == MAIL_NO_ERROR) + generic_cache_store(filename, * result, * result_len); + + return r; +} + +static int imap_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + r = mailmessage_get_flags(get_ancestor(msg_info), &flags); + if (r != MAIL_NO_ERROR) + return r; + + get_ancestor(msg_info)->msg_flags = NULL; + msg_info->msg_flags = flags; + * result = flags; + + return MAIL_NO_ERROR; +} + +#define ENV_NAME "env.db" + +static int imap_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result) +{ + struct mailimf_fields * fields; + int r; + struct mail_cache_db * cache_db; + MMAPString * mmapstr; + char filename[PATH_MAX]; + struct imap_cached_session_state_data * data; + int res; + + data = get_cached_session_data(msg_info); + if (data->imap_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME); + + r = mail_cache_db_open_lock(filename, &cache_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db; + } + + r = imapdriver_get_cached_envelope(cache_db, mmapstr, + msg_info->msg_session, msg_info, &fields); + + if ((r != MAIL_ERROR_CACHE_MISS) && (r != MAIL_NO_ERROR)) { + res = r; + goto close_db; + } + + r = mailmessage_fetch_envelope(get_ancestor(msg_info), &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_db; + } + + r = imapdriver_write_cached_envelope(cache_db, mmapstr, + msg_info->msg_session, msg_info, fields); + + * result = fields; + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename, cache_db); + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(filename, cache_db); + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_cached_message.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_cached_message.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_cached_message.h,v 1.6 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef IMAPDRIVER_CACHED_MESSAGE_H + +#define IMAPDRIVER_CACHED_MESSAGE_H + +#include <libetpan/imapdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * imap_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_message.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_message.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1268 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_message.c,v 1.24 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "imapdriver_message.h" + +#include "imapdriver_tools.h" +#include "imapdriver.h" +#include "imapdriver_types.h" +#include "mailimap.h" +#include "maildriver_tools.h" +#include "generic_cache.h" + +#include <stdlib.h> +#include <string.h> + +static int imap_initialize(mailmessage * msg_info); + +static void imap_fetch_result_free(mailmessage * msg_info, + char * msg); + +static int imap_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int imap_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int imap_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + +static int imap_fetch_size(mailmessage * msg_info, + size_t * result); + +static int imap_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + +static int imap_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +static int imap_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +static int imap_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +static int imap_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +static int imap_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + +static int imap_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static void imap_flush(mailmessage * msg_info); + +static void imap_check(mailmessage * msg_info); + +static mailmessage_driver local_imap_message_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* msg_name */ "imap", + + /* msg_initialize */ imap_initialize, + /* msg_uninitialize */ NULL, + + /* msg_flush */ imap_flush, + /* msg_check */ imap_check, + + /* msg_fetch_result_free */ imap_fetch_result_free, + + /* msg_fetch */ imap_fetch, + /* msg_fetch_header */ imap_fetch_header, + /* msg_fetch_body */ imap_fetch_body, + /* msg_fetch_size */ imap_fetch_size, + /* msg_get_bodystructure */ imap_get_bodystructure, + /* msg_fetch_section */ imap_fetch_section, + /* msg_fetch_section_header */ imap_fetch_section_header, + /* msg_fetch_section_mime */ imap_fetch_section_mime, + /* msg_fetch_section_body */ imap_fetch_section_body, + /* msg_fetch_envelope */ imap_fetch_envelope, + + /* msg_get_flags */ imap_get_flags, +#else + .msg_name = "imap", + + .msg_initialize = imap_initialize, + .msg_uninitialize = NULL, + + .msg_flush = imap_flush, + .msg_check = imap_check, + + .msg_fetch_result_free = imap_fetch_result_free, + + .msg_fetch = imap_fetch, + .msg_fetch_header = imap_fetch_header, + .msg_fetch_body = imap_fetch_body, + .msg_fetch_size = imap_fetch_size, + .msg_get_bodystructure = imap_get_bodystructure, + .msg_fetch_section = imap_fetch_section, + .msg_fetch_section_header = imap_fetch_section_header, + .msg_fetch_section_mime = imap_fetch_section_mime, + .msg_fetch_section_body = imap_fetch_section_body, + .msg_fetch_envelope = imap_fetch_envelope, + + .msg_get_flags = imap_get_flags, +#endif +}; + +mailmessage_driver * imap_message_driver = &local_imap_message_driver; + +static inline struct imap_session_state_data * +get_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailimap * get_imap_session(mailmessage * msg) +{ + return get_session_data(msg)->imap_session; +} + + + +static int imap_initialize(mailmessage * msg_info) +{ + char key[PATH_MAX]; + char * uid; + mailimap * imap; + + imap = get_imap_session(msg_info); + + snprintf(key, PATH_MAX, "%u-%u", + imap->imap_selection_info->sel_uidvalidity, msg_info->msg_index); + + uid = strdup(key); + if (uid == NULL) { + return MAIL_ERROR_MEMORY; + } + + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + + +static void imap_fetch_result_free(mailmessage * msg_info, + char * msg) +{ + if (msg != NULL) { + if (mmap_string_unref(msg) != 0) + free(msg); + } +} + + +static void imap_flush(mailmessage * msg_info) +{ + if (msg_info->msg_mime != NULL) { + mailmime_free(msg_info->msg_mime); + msg_info->msg_mime = NULL; + } +} + +static void imap_check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_session_data(msg_info)->imap_flags_store, + msg_info); + /* ignore errors */ + } +} + +static int imap_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + char * text; + size_t text_length; + int res; + clistiter * cur; + struct mailimap_section * section; + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + +#if 0 + fetch_att = mailimap_fetch_att_new_rfc822(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info->session), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); +#endif + + section = mailimap_section_new(NULL); + if (section == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + if (clist_begin(fetch_result) == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_begin(fetch_result)->data; + + text = NULL; + text_length = 0; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = clist_content(cur); + + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { +#if 0 + if (msg_att_item->msg_att_static->type == MAILIMAP_MSG_ATT_RFC822) { + text = msg_att_item->msg_att_static->rfc822; + msg_att_item->msg_att_static->rfc822 = NULL; + text_length = msg_att_item->msg_att_static->length; + } +#endif + if (msg_att_item->att_data.att_static->att_type == + MAILIMAP_MSG_ATT_BODY_SECTION) { + text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; + /* detach */ + msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; + text_length = + msg_att_item->att_data.att_static->att_data.att_body_section->sec_length; + } + } + } + + mailimap_fetch_list_free(fetch_result); + + if (text == NULL) + return MAIL_ERROR_FETCH; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; + + free_fetch_att: + mailimap_fetch_att_free(fetch_att); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static int imap_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + char * text; + size_t text_length; + int res; + clistiter * cur; + struct mailimap_section * section; + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + +#if 0 + fetch_att = mailimap_fetch_att_new_rfc822_header(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info->session), + set, fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); +#endif + + section = mailimap_section_new_header(); + if (section == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + if (clist_begin(fetch_result) == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_begin(fetch_result)->data; + + text = NULL; + text_length = 0; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = clist_content(cur); + + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { +#if 0 + if (msg_att_item->msg_att_static->type == + MAILIMAP_MSG_ATT_RFC822_HEADER) { + text = msg_att_item->msg_att_static->rfc822_header; + msg_att_item->msg_att_static->rfc822_header = NULL; + text_length = msg_att_item->msg_att_static->length; + } +#endif + if (msg_att_item->att_data.att_static->att_type == + MAILIMAP_MSG_ATT_BODY_SECTION) { + text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; + msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; + text_length = + msg_att_item->att_data.att_static->att_data.att_body_section->sec_length; + } + } + } + + mailimap_fetch_list_free(fetch_result); + + if (text == NULL) + return MAIL_ERROR_FETCH; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; + + free_fetch_att: + mailimap_fetch_att_free(fetch_att); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static int imap_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + char * text; + size_t text_length; + int res; + clistiter * cur; + struct mailimap_section * section; + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + +#if 0 + fetch_att = mailimap_fetch_att_new_rfc822_text(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info->session), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); +#endif + section = mailimap_section_new_text(); + if (section == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + cur = clist_begin(fetch_result); + if (cur == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_content(cur); + + text = NULL; + text_length = 0; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = clist_content(cur); + + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { +#if 0 + if (msg_att_item->msg_att_static->type == + MAILIMAP_MSG_ATT_RFC822_TEXT) { + text = msg_att_item->msg_att_static->rfc822_text; + msg_att_item->msg_att_static->rfc822_text = NULL; + text_length = msg_att_item->msg_att_static->length; + } +#endif + if (msg_att_item->att_data.att_static->att_type == + MAILIMAP_MSG_ATT_BODY_SECTION) { + text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; + msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; + text_length = + msg_att_item->att_data.att_static->att_data.att_body_section->sec_length; + } + } + } + + mailimap_fetch_list_free(fetch_result); + + if (text == NULL) + return MAIL_ERROR_FETCH; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; + + free_fetch_att: + mailimap_fetch_att_free(fetch_att); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static int imap_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + size_t size; + int res; + clistiter * cur; + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_att = mailimap_fetch_att_new_rfc822_size(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_att; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + case MAILIMAP_ERROR_STREAM: + return MAIL_ERROR_STREAM; + case MAILIMAP_NO_ERROR: + break; + default: + return MAIL_ERROR_FETCH; + } + + if (clist_begin(fetch_result) == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_begin(fetch_result)->data; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = clist_content(cur); + + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { + + if (msg_att_item->att_data.att_static->att_type == + MAILIMAP_MSG_ATT_RFC822_SIZE) { + size = msg_att_item->att_data.att_static->att_data.att_rfc822_size; + + * result = size; + + mailimap_fetch_list_free(fetch_result); + return MAIL_NO_ERROR; + } + } + } + + mailimap_fetch_list_free(fetch_result); + + return MAIL_ERROR_FETCH; + + free_fetch_att: + mailimap_fetch_att_free(fetch_att); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static int imap_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + struct mailimap_body * imap_body; + struct mailmime * body; + int res; + struct mailimf_fields * fields; + struct mailmime * new_body; + struct mailmime_content * content_message; + struct mailimap_envelope * envelope; + uint32_t uid; + char * references; + size_t ref_size; + clistiter * cur; + + if (msg_info->msg_mime != NULL) { + * result = msg_info->msg_mime; + + return MAIL_NO_ERROR; + } + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + fetch_att = mailimap_fetch_att_new_bodystructure(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = imap_add_envelope_fetch_att(fetch_type); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_fetch_type; + } + + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + cur = clist_begin(fetch_result); + if (cur == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_content(cur); + + uid = 0; + references = NULL; + ref_size = 0; + imap_body = NULL; + envelope = NULL; + + r = imap_get_msg_att_info(msg_att, + &uid, &envelope, &references, &ref_size, NULL, &imap_body); + if (r != MAIL_NO_ERROR) { + mailimap_fetch_list_free(fetch_result); + res = r; + goto err; + } + + if (uid != msg_info->msg_index) { + mailimap_fetch_list_free(fetch_result); + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + if (imap_body == NULL) { + mailimap_fetch_list_free(fetch_result); + res = MAIL_ERROR_FETCH; + goto err; + } + + r = imap_body_to_body(imap_body, &body); + if (r != MAIL_NO_ERROR) { + mailimap_fetch_list_free(fetch_result); + res = r; + goto err; + } + + fields = NULL; + if (envelope != NULL) { + r = imap_env_to_fields(envelope, references, ref_size, &fields); + if (r != MAIL_NO_ERROR) { + mailmime_free(body); + mailimap_fetch_list_free(fetch_result); + res = r; + goto err; + } + } + + content_message = mailmime_get_content_message(); + if (content_message == NULL) { + if (fields != NULL) + mailimf_fields_free(fields); + mailmime_free(body); + mailimap_fetch_list_free(fetch_result); + res = MAIL_ERROR_MEMORY; + goto err; + } + + new_body = mailmime_new(MAILMIME_MESSAGE, NULL, + 0, NULL, content_message, + NULL, NULL, NULL, NULL, fields, body); + + if (new_body == NULL) { + mailmime_content_free(content_message); + if (fields != NULL) + mailimf_fields_free(fields); + mailmime_free(body); + mailimap_fetch_list_free(fetch_result); + res = MAIL_ERROR_MEMORY; + goto err; + } + msg_info->msg_mime = new_body; + + mailimap_fetch_list_free(fetch_result); + + * result = new_body; + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static int +fetch_imap(mailmessage * msg, + struct mailimap_fetch_type * fetch_type, + char ** result, size_t * result_len) +{ + int r; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * msg_att_item; + clist * fetch_result; + struct mailimap_set * set; + char * text; + size_t text_length; + clistiter * cur; + + set = mailimap_set_new_single(msg->msg_index); + if (set == NULL) + return MAIL_ERROR_MEMORY; + + r = mailimap_uid_fetch(get_imap_session(msg), set, + fetch_type, &fetch_result); + + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + if (clist_begin(fetch_result) == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_begin(fetch_result)->data; + + text = NULL; + text_length = 0; + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + msg_att_item = clist_content(cur); + + if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { + + if (msg_att_item->att_data.att_static->att_type == + MAILIMAP_MSG_ATT_BODY_SECTION) { + text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part; + msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL; + text_length = + msg_att_item->att_data.att_static->att_data.att_body_section->sec_length; + } + } + } + + mailimap_fetch_list_free(fetch_result); + + if (text == NULL) + return MAIL_ERROR_FETCH; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; +} + + +static int imap_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + struct mailimap_section * section; + struct mailimap_fetch_att * fetch_att; + int r; + struct mailimap_fetch_type * fetch_type; + char * text; + size_t text_length; + struct mailmime_section * part; + + if (mime->mm_parent == NULL) + return imap_fetch(msg_info, result, result_len); + + r = mailmime_get_section_id(mime, &part); + if (r != MAILIMF_NO_ERROR) + return maildriver_imf_error_to_mail_error(r); + + r = section_to_imap_section(part, IMAP_SECTION_MESSAGE, §ion); + mailmime_section_free(part); + if (r != MAIL_NO_ERROR) + return r; + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + return MAIL_ERROR_MEMORY; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + mailimap_fetch_att_free(fetch_att); + return MAIL_ERROR_MEMORY; + } + + r = fetch_imap(msg_info, fetch_type, &text, &text_length); + + mailimap_fetch_type_free(fetch_type); + + if (r != MAIL_NO_ERROR) + return r; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; +} + +static int imap_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + struct mailimap_section * section; + struct mailimap_fetch_att * fetch_att; + int r; + struct mailimap_fetch_type * fetch_type; + char * text; + size_t text_length; + struct mailmime_section * part; + + if (mime->mm_parent == NULL) + return imap_fetch_header(msg_info, result, result_len); + + r = mailmime_get_section_id(mime, &part); + if (r != MAILIMF_NO_ERROR) + return maildriver_imf_error_to_mail_error(r); + + r = section_to_imap_section(part, IMAP_SECTION_HEADER, §ion); + mailmime_section_free(part); + if (r != MAIL_NO_ERROR) + return r; + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + return MAIL_ERROR_MEMORY; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + mailimap_fetch_att_free(fetch_att); + return MAIL_ERROR_MEMORY; + } + + r = fetch_imap(msg_info, fetch_type, &text, &text_length); + mailimap_fetch_type_free(fetch_type); + + if (r != MAIL_NO_ERROR) + return r; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; +} + +static int imap_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + struct mailimap_section * section; + struct mailimap_fetch_att * fetch_att; + int r; + struct mailimap_fetch_type * fetch_type; + char * text; + size_t text_length; + struct mailmime_section * part; + + if (mime->mm_parent == NULL) + return MAIL_ERROR_INVAL; + + if (mime->mm_parent->mm_parent == NULL) + return imap_fetch_header(msg_info, result, result_len); + + r = mailmime_get_section_id(mime, &part); + if (r != MAILIMF_NO_ERROR) + return maildriver_imf_error_to_mail_error(r); + + r = section_to_imap_section(part, IMAP_SECTION_MIME, §ion); + mailmime_section_free(part); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_MEMORY; + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + return MAIL_ERROR_MEMORY; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + mailimap_fetch_att_free(fetch_att); + return MAIL_ERROR_MEMORY; + } + + r = fetch_imap(msg_info, fetch_type, &text, &text_length); + + mailimap_fetch_type_free(fetch_type); + + if (r != MAIL_NO_ERROR) + return r; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; +} + +static int imap_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + struct mailimap_section * section; + struct mailimap_fetch_att * fetch_att; + int r; + struct mailimap_fetch_type * fetch_type; + char * text; + size_t text_length; + struct mailmime_section * part; + + if (mime->mm_parent == NULL) + return imap_fetch_body(msg_info, result, result_len); + + if (mime->mm_parent->mm_parent == NULL) + return imap_fetch_body(msg_info, result, result_len); + + r = mailmime_get_section_id(mime, &part); + if (r != MAILIMF_NO_ERROR) + return maildriver_imf_error_to_mail_error(r); + + r = section_to_imap_section(part, IMAP_SECTION_BODY, §ion); + mailmime_section_free(part); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_MEMORY; + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + return MAIL_ERROR_MEMORY; + } + + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + if (fetch_type == NULL) { + mailimap_fetch_att_free(fetch_att); + return MAIL_ERROR_MEMORY; + } + + r = fetch_imap(msg_info, fetch_type, &text, &text_length); + + mailimap_fetch_type_free(fetch_type); + + if (r != MAIL_NO_ERROR) + return r; + + * result = text; + * result_len = text_length; + + return MAIL_NO_ERROR; +} + +static int imap_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + flags = mail_flags_store_get(get_session_data(msg_info)->imap_flags_store, + msg_info->msg_index); + + if (flags == NULL) { + r = imap_fetch_flags(get_imap_session(msg_info), + msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) + return r; + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; +} + +static int imap_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result) +{ + int r; + struct mailimap_set * set; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + clist * fetch_result; + struct mailimap_msg_att * msg_att; + int res; + struct mailimf_fields * fields; + struct mailimap_envelope * envelope; + uint32_t uid; + char * references; + size_t ref_size; + + set = mailimap_set_new_single(msg_info->msg_index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = imap_add_envelope_fetch_att(fetch_type); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_fetch_type; + } + + r = mailimap_uid_fetch(get_imap_session(msg_info), set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + if (clist_begin(fetch_result) == NULL) { + mailimap_fetch_list_free(fetch_result); + return MAIL_ERROR_FETCH; + } + + msg_att = clist_begin(fetch_result)->data; + + uid = 0; + references = NULL; + ref_size = 0; + envelope = NULL; + + r = imap_get_msg_att_info(msg_att, + &uid, + &envelope, + &references, + &ref_size, + NULL, + NULL); + if (r != MAIL_NO_ERROR) { + mailimap_fetch_list_free(fetch_result); + res = r; + goto err; + } + + if (uid != msg_info->msg_index) { + mailimap_fetch_list_free(fetch_result); + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + fields = NULL; + if (envelope != NULL) { + r = imap_env_to_fields(envelope, references, ref_size, &fields); + if (r != MAIL_NO_ERROR) { + mailimap_fetch_list_free(fetch_result); + res = r; + goto err; + } + } + + mailimap_fetch_list_free(fetch_result); + + * result = fields; + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + free_set: + mailimap_set_free(set); + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_message.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_message.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_message.h,v 1.6 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef IMAPDRIVER_MESSAGE_H + +#define IMAPDRIVER_MESSAGE_H + +#include <libetpan/imapdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * imap_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_tools.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_tools.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3637 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_tools.c,v 1.22 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "imapdriver_tools.h" + +#include "maildriver.h" + +#include <stdlib.h> +#include <string.h> + +#include "mail.h" +#include "imapdriver_types.h" +#include "maildriver_tools.h" +#include "generic_cache.h" +#include "mailmessage.h" +#include "mail_cache_db.h" + + + +static inline struct imap_session_state_data * +session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct imap_cached_session_state_data * +cached_session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * +cached_session_get_ancestor(mailsession * session) +{ + return cached_session_get_data(session)->imap_ancestor; +} + +static inline struct imap_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return session_get_data(cached_session_get_ancestor(session)); +} + +static inline mailimap * +cached_session_get_imap_session(mailsession * session) +{ + return cached_session_get_ancestor_data(session)->imap_session; +} + +static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn, + struct mail_flags ** result); + + +int imap_error_to_mail_error(int error) +{ + switch (error) { + case MAILIMAP_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILIMAP_NO_ERROR_AUTHENTICATED: + return MAIL_NO_ERROR_AUTHENTICATED; + + case MAILIMAP_NO_ERROR_NON_AUTHENTICATED: + return MAIL_NO_ERROR_NON_AUTHENTICATED; + + case MAILIMAP_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + + case MAILIMAP_ERROR_STREAM: + return MAIL_ERROR_STREAM; + + case MAILIMAP_ERROR_PARSE: + return MAIL_ERROR_PARSE; + + case MAILIMAP_ERROR_CONNECTION_REFUSED: + return MAIL_ERROR_CONNECT; + + case MAILIMAP_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILIMAP_ERROR_FATAL: + return MAIL_ERROR_FATAL; + + case MAILIMAP_ERROR_PROTOCOL: + return MAIL_ERROR_PROTOCOL; + + case MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION: + return MAIL_ERROR_CONNECT; + + case MAILIMAP_ERROR_APPEND: + return MAIL_ERROR_APPEND; + + case MAILIMAP_ERROR_NOOP: + return MAIL_ERROR_NOOP; + + case MAILIMAP_ERROR_LOGOUT: + return MAIL_ERROR_LOGOUT; + + case MAILIMAP_ERROR_CAPABILITY: + return MAIL_ERROR_CAPABILITY; + + case MAILIMAP_ERROR_CHECK: + return MAIL_ERROR_CHECK; + + case MAILIMAP_ERROR_CLOSE: + return MAIL_ERROR_CLOSE; + + case MAILIMAP_ERROR_EXPUNGE: + return MAIL_ERROR_EXPUNGE; + + case MAILIMAP_ERROR_COPY: + case MAILIMAP_ERROR_UID_COPY: + return MAIL_ERROR_COPY; + + case MAILIMAP_ERROR_CREATE: + return MAIL_ERROR_CREATE; + + case MAILIMAP_ERROR_DELETE: + return MAIL_ERROR_DELETE; + + case MAILIMAP_ERROR_EXAMINE: + return MAIL_ERROR_EXAMINE; + + case MAILIMAP_ERROR_FETCH: + case MAILIMAP_ERROR_UID_FETCH: + return MAIL_ERROR_FETCH; + + case MAILIMAP_ERROR_LIST: + return MAIL_ERROR_LIST; + + case MAILIMAP_ERROR_LOGIN: + return MAIL_ERROR_LOGIN; + + case MAILIMAP_ERROR_LSUB: + return MAIL_ERROR_LSUB; + + case MAILIMAP_ERROR_RENAME: + return MAIL_ERROR_RENAME; + + case MAILIMAP_ERROR_SEARCH: + case MAILIMAP_ERROR_UID_SEARCH: + return MAIL_ERROR_SEARCH; + + case MAILIMAP_ERROR_SELECT: + return MAIL_ERROR_SELECT; + + case MAILIMAP_ERROR_STATUS: + return MAIL_ERROR_STATUS; + + case MAILIMAP_ERROR_STORE: + case MAILIMAP_ERROR_UID_STORE: + return MAIL_ERROR_STORE; + + case MAILIMAP_ERROR_SUBSCRIBE: + return MAIL_ERROR_SUBSCRIBE; + + case MAILIMAP_ERROR_UNSUBSCRIBE: + return MAIL_ERROR_UNSUBSCRIBE; + + case MAILIMAP_ERROR_STARTTLS: + return MAIL_ERROR_STARTTLS; + + case MAILIMAP_ERROR_INVAL: + return MAIL_ERROR_INVAL; + + default: + return MAIL_ERROR_INVAL; + } +} + + + + + +static int +imap_body_parameter_to_content(struct mailimap_body_fld_param * + body_parameter, + char * subtype, + struct mailmime_type * mime_type, + struct mailmime_content ** result); + +static int +imap_body_type_text_to_content_type(char * subtype, + struct mailimap_body_fld_param * + body_parameter, + struct mailmime_content ** result); + + +int imap_list_to_list(clist * imap_list, struct mail_list ** result) +{ + clistiter * cur; + clist * list; + struct mail_list * resp; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(imap_list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_mailbox_list * mb_list; + char * new_mb; + + mb_list = clist_content(cur); + + new_mb = strdup(mb_list->mb_name); + if (new_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, new_mb); + if (r != 0) { + free(new_mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + resp = mail_list_new(list); + if (resp == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = resp; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + err: + return res; +} + +int +section_to_imap_section(struct mailmime_section * section, int type, + struct mailimap_section ** result) +{ + struct mailimap_section_part * section_part; + struct mailimap_section * imap_section; + clist * list; + clistiter * cur; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(section->sec_list) ; cur != NULL ; + cur = clist_next(cur)) { + uint32_t value; + uint32_t * id; + + value = * (uint32_t *) clist_content(cur); + id = malloc(sizeof(* id)); + if (id == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + * id = value; + r = clist_append(list, id); + if (r != 0) { + res = MAIL_ERROR_MEMORY; + free(id); + goto free_list; + } + } + + section_part = mailimap_section_part_new(list); + if (section_part == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + imap_section = NULL; + + switch (type) { + case IMAP_SECTION_MESSAGE: + imap_section = mailimap_section_new_part(section_part); + break; + case IMAP_SECTION_HEADER: + imap_section = mailimap_section_new_part_header(section_part); + break; + case IMAP_SECTION_MIME: + imap_section = mailimap_section_new_part_mime(section_part); + break; + case IMAP_SECTION_BODY: + imap_section = mailimap_section_new_part_text(section_part); + break; + } + + if (imap_section == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_part; + } + + * result = imap_section; + + return MAIL_NO_ERROR; + + free_part: + mailimap_section_part_free(section_part); + free_list: + if (list != NULL) { + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + } + err: + return res; +} + + + +static int +imap_body_media_basic_to_content_type(struct mailimap_media_basic * + media_basic, + struct mailimap_body_fld_param * + body_parameter, + struct mailmime_content ** result) +{ + struct mailmime_content * content; + struct mailmime_type * mime_type; + struct mailmime_discrete_type * discrete_type; + struct mailmime_composite_type * composite_type; + char * discrete_type_extension; + int discrete_type_type; + int composite_type_type; + int mime_type_type; + char * subtype; + int r; + int res; + + discrete_type = NULL; + composite_type = NULL; + discrete_type_extension = NULL; + subtype = NULL; + discrete_type_type = 0; + composite_type_type = 0; + mime_type_type = 0; + + switch (media_basic->med_type) { + case MAILIMAP_MEDIA_BASIC_APPLICATION: + mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE; + discrete_type_type = MAILMIME_DISCRETE_TYPE_APPLICATION; + break; + + case MAILIMAP_MEDIA_BASIC_AUDIO: + mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE; + discrete_type_type = MAILMIME_DISCRETE_TYPE_APPLICATION; + break; + + case MAILIMAP_MEDIA_BASIC_IMAGE: + mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE; + discrete_type_type = MAILMIME_DISCRETE_TYPE_IMAGE; + break; + + case MAILIMAP_MEDIA_BASIC_MESSAGE: + mime_type_type = MAILMIME_TYPE_COMPOSITE_TYPE; + composite_type_type = MAILMIME_COMPOSITE_TYPE_MESSAGE; + break; + + case MAILIMAP_MEDIA_BASIC_VIDEO: + mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE; + discrete_type_type = MAILMIME_DISCRETE_TYPE_VIDEO; + break; + + case MAILIMAP_MEDIA_BASIC_OTHER: + mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE; + discrete_type_type = MAILMIME_DISCRETE_TYPE_EXTENSION; + discrete_type_extension = media_basic->med_basic_type; + if (discrete_type_extension == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + break; + + default: + res = MAIL_ERROR_INVAL; + goto err; + } + + switch (mime_type_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + if (discrete_type_extension != NULL) { + discrete_type_extension = strdup(discrete_type_extension); + if (discrete_type_extension == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + } + + discrete_type = mailmime_discrete_type_new(discrete_type_type, + discrete_type_extension); + if (discrete_type == NULL) { + if (discrete_type_extension != NULL) + free(discrete_type_extension); + res = MAIL_ERROR_MEMORY; + goto err; + } + + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + composite_type = mailmime_composite_type_new(composite_type_type, + NULL); + if (composite_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + break; + + default: + res = MAIL_ERROR_INVAL; + goto err; + } + + mime_type = mailmime_type_new(mime_type_type, discrete_type, composite_type); + if (mime_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = imap_body_parameter_to_content(body_parameter, media_basic->med_subtype, + mime_type, &content); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_type; + } + + * result = content; + + return MAIL_NO_ERROR; + + free_type: + mailmime_type_free(mime_type); + free: + if (discrete_type != NULL) + mailmime_discrete_type_free(discrete_type); + if (composite_type != NULL) + mailmime_composite_type_free(composite_type); + err: + return res; +} + +static int +imap_disposition_to_mime_disposition(struct mailimap_body_fld_dsp * imap_dsp, + struct mailmime_disposition ** result) +{ + size_t cur_token; + int r; + struct mailmime_disposition_type * dsp_type; + struct mailmime_disposition * dsp; + clist * parameters; + int res; + + cur_token = 0; + r = mailmime_disposition_type_parse(imap_dsp->dsp_type, + strlen(imap_dsp->dsp_type), &cur_token, &dsp_type); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + parameters = clist_new(); + if (parameters == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (imap_dsp->dsp_attributes != NULL) { + clistiter * cur; + + for(cur = clist_begin(imap_dsp->dsp_attributes->pa_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_single_body_fld_param * imap_param; + struct mailmime_disposition_parm * dsp_param; + struct mailmime_parameter * param; + char * filename; + char * creation_date; + char * modification_date; + char * read_date; + size_t size; + int type; + + imap_param = clist_content(cur); + + filename = NULL; + creation_date = NULL; + modification_date = NULL; + read_date = NULL; + size = 0; + param = NULL; + + type = mailmime_disposition_guess_type(imap_param->pa_name, + strlen(imap_param->pa_name), 0); + + switch (type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + if (strcasecmp(imap_param->pa_name, "filename") != 0) { + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + break; + } + filename = strdup(imap_param->pa_value); + if (filename == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + if (strcasecmp(imap_param->pa_name, "creation-date") != 0) { + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + break; + } + creation_date = strdup(imap_param->pa_value); + if (creation_date == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + if (strcasecmp(imap_param->pa_name, "modification-date") != 0) { + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + break; + } + modification_date = strdup(imap_param->pa_value); + if (modification_date == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + if (strcasecmp(imap_param->pa_name, "read-date") != 0) { + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + break; + } + read_date = strdup(imap_param->pa_value); + if (read_date == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + if (strcasecmp(imap_param->pa_name, "size") != 0) { + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + break; + } + size = strtoul(imap_param->pa_value, NULL, 10); + break; + } + + if (type == MAILMIME_DISPOSITION_PARM_PARAMETER) { + char * name; + char * value; + + name = strdup(imap_param->pa_name); + if (name == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + + value = strdup(imap_param->pa_value); + if (value == NULL) { + res = MAIL_ERROR_MEMORY; + free(name); + goto free_dsp_type; + } + + param = mailmime_parameter_new(name, value); + if (param == NULL) { + free(value); + free(name); + res = MAIL_ERROR_MEMORY; + goto free_dsp_type; + } + + } + + dsp_param = mailmime_disposition_parm_new(type, filename, + creation_date, + modification_date, + read_date, + size, param); + if (dsp_param == NULL) { + if (filename != NULL) + free(filename); + if (creation_date != NULL) + free(creation_date); + if (modification_date != NULL) + free(modification_date); + if (read_date != NULL) + free(read_date); + if (param != NULL) + mailmime_parameter_free(param); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(parameters, dsp_param); + if (r != 0) { + mailmime_disposition_parm_free(dsp_param); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + dsp = mailmime_disposition_new(dsp_type, parameters); + if (dsp == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = dsp; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(parameters, + (clist_func) mailmime_disposition_parm_free, NULL); + clist_free(parameters); + free_dsp_type: + mailmime_disposition_type_free(dsp_type); + err: + return res; +} + +static int +imap_language_to_mime_language(struct mailimap_body_fld_lang * imap_lang, + struct mailmime_language ** result) +{ + clist * list; + clistiter * cur; + int res; + char * single; + int r; + struct mailmime_language * lang; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + switch (imap_lang->lg_type) { + case MAILIMAP_BODY_FLD_LANG_SINGLE: + if (imap_lang->lg_data.lg_single != NULL) { + single = strdup(imap_lang->lg_data.lg_single); + if (single == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + r = clist_append(list, single); + if (r < 0) { + free(single); + res = MAIL_ERROR_MEMORY; + goto free; + } + } + + break; + + case MAILIMAP_BODY_FLD_LANG_LIST: + for(cur = clist_begin(imap_lang->lg_data.lg_list) ; + cur != NULL ; cur = clist_next(cur)) { + char * original_single; + + original_single = clist_content(cur); + + single = strdup(original_single); + if (single == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + r = clist_append(list, single); + if (r < 0) { + free(single); + res = MAIL_ERROR_MEMORY; + goto free; + } + } + } + + lang = mailmime_language_new(list); + if (lang == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + * result = lang; + + return MAIL_NO_ERROR; + + free: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + err: + return res; +} + +static int +imap_body_fields_to_mime_fields(struct mailimap_body_fields * body_fields, + struct mailimap_body_fld_dsp * imap_dsp, + struct mailimap_body_fld_lang * imap_lang, + struct mailmime_fields ** result, + uint32_t * pbody_size) +{ + struct mailmime_field * mime_field; + struct mailmime_fields * mime_fields; + clist * list; + char * id; + struct mailmime_mechanism * encoding; + char * description; + struct mailmime_disposition * dsp; + struct mailmime_language * lang; + int type; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (body_fields != NULL) { + + if (pbody_size != NULL) + * pbody_size = body_fields->bd_size; + + if (body_fields->bd_id != NULL) { + type = MAILMIME_FIELD_ID; + id = strdup(body_fields->bd_id); + if (id == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + mime_field = mailmime_field_new(type, NULL, + NULL, id, NULL, 0, NULL, NULL); + if (mime_field == NULL) { + free(id); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (body_fields->bd_description != NULL) { + type = MAILMIME_FIELD_DESCRIPTION; + description = strdup(body_fields->bd_description); + if (description == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + mime_field = mailmime_field_new(type, NULL, + NULL, NULL, description, 0, NULL, NULL); + if (mime_field == NULL) { + free(description); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (body_fields->bd_encoding != NULL) { + char * encoding_value; + int encoding_type; + + type = MAILMIME_FIELD_TRANSFER_ENCODING; + + encoding_value = NULL; + switch (body_fields->bd_encoding->enc_type) { + case MAILIMAP_BODY_FLD_ENC_7BIT: + encoding_type = MAILMIME_MECHANISM_7BIT; + break; + case MAILIMAP_BODY_FLD_ENC_8BIT: + encoding_type = MAILMIME_MECHANISM_8BIT; + break; + case MAILIMAP_BODY_FLD_ENC_BINARY: + encoding_type = MAILMIME_MECHANISM_BINARY; + break; + case MAILIMAP_BODY_FLD_ENC_BASE64: + encoding_type = MAILMIME_MECHANISM_BASE64; + break; + case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE: + encoding_type = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + break; + case MAILIMAP_BODY_FLD_ENC_OTHER: + encoding_type = MAILMIME_MECHANISM_TOKEN; + encoding_value = strdup(body_fields->bd_encoding->enc_value); + if (encoding_value == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + default: + res = MAIL_ERROR_INVAL; + goto free_list; + } + + encoding = mailmime_mechanism_new(encoding_type, encoding_value); + if (encoding == NULL) { + if (encoding_value != NULL) + free(encoding_value); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + mime_field = mailmime_field_new(type, NULL, + encoding, NULL, NULL, 0, NULL, NULL); + if (mime_field == NULL) { + mailmime_mechanism_free(encoding); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (imap_dsp != NULL) { + r = imap_disposition_to_mime_disposition(imap_dsp, &dsp); + if (r != MAIL_ERROR_PARSE) { + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + type = MAILMIME_FIELD_DISPOSITION; + + mime_field = mailmime_field_new(type, NULL, + NULL, NULL, NULL, 0, dsp, NULL); + if (mime_field == NULL) { + mailmime_disposition_free(dsp); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (imap_lang != NULL) { + r = imap_language_to_mime_language(imap_lang, &lang); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + type = MAILMIME_FIELD_LANGUAGE; + + mime_field = mailmime_field_new(type, NULL, + NULL, NULL, NULL, 0, NULL, lang); + if (mime_field == NULL) { + mailmime_language_free(lang); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, mime_field); + if (r != 0) { + mailmime_field_free(mime_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + mime_fields = mailmime_fields_new(list); + if (mime_fields == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = mime_fields; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_fields_free, NULL); + clist_free(list); + err: + return res; +} + +static int +imap_body_type_basic_to_body(struct mailimap_body_type_basic * + imap_type_basic, + struct mailimap_body_ext_1part * + body_ext_1part, + struct mailmime ** result) +{ + struct mailmime_content * content; + struct mailmime_fields * mime_fields; + struct mailmime * body; + int r; + int res; + uint32_t mime_size; + + content = NULL; + r = imap_body_media_basic_to_content_type(imap_type_basic->bd_media_basic, + imap_type_basic->bd_fields->bd_parameter, &content); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (body_ext_1part != NULL) + r = imap_body_fields_to_mime_fields(imap_type_basic->bd_fields, + body_ext_1part->bd_disposition, + body_ext_1part->bd_language, + &mime_fields, &mime_size); + else + r = imap_body_fields_to_mime_fields(imap_type_basic->bd_fields, + NULL, NULL, + &mime_fields, &mime_size); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_content; + } + + body = mailmime_new(MAILMIME_SINGLE, NULL, + mime_size, mime_fields, content, + NULL, NULL, NULL, NULL, NULL, NULL); + + if (body == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + * result = body; + + return MAIL_NO_ERROR; + + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return res; +} + +static int +imap_body_type_text_to_body(struct mailimap_body_type_text * + imap_type_text, + struct mailimap_body_ext_1part * + body_ext_1part, + struct mailmime ** result) +{ + struct mailmime_content * content; + struct mailmime_fields * mime_fields; + struct mailmime * body; + int r; + int res; + uint32_t mime_size; + + r = imap_body_type_text_to_content_type(imap_type_text->bd_media_text, + imap_type_text->bd_fields->bd_parameter, + &content); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (body_ext_1part == NULL) { + r = imap_body_fields_to_mime_fields(imap_type_text->bd_fields, + NULL, NULL, + &mime_fields, &mime_size); + } + else { + r = imap_body_fields_to_mime_fields(imap_type_text->bd_fields, + body_ext_1part->bd_disposition, + body_ext_1part->bd_language, + &mime_fields, &mime_size); + } + if (r != MAIL_NO_ERROR) { + res = r; + goto free_content; + } + + body = mailmime_new(MAILMIME_SINGLE, NULL, + mime_size, mime_fields, content, + NULL, NULL, NULL, NULL, NULL, NULL); + + if (body == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + * result = body; + + return MAIL_NO_ERROR; + + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return res; +} + +static int +imap_body_parameter_to_content(struct mailimap_body_fld_param * + body_parameter, + char * subtype, + struct mailmime_type * mime_type, + struct mailmime_content ** result) +{ + clist * parameters; + char * new_subtype; + struct mailmime_content * content; + int r; + int res; + + new_subtype = strdup(subtype); + if (new_subtype == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + parameters = clist_new(); + if (parameters == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_subtype; + } + + if (body_parameter != NULL) { + clistiter * cur; + + for(cur = clist_begin(body_parameter->pa_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_single_body_fld_param * imap_param; + struct mailmime_parameter * param; + char * name; + char * value; + + imap_param = clist_content(cur); + name = strdup(imap_param->pa_name); + if (name == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_parameters; + } + + value = strdup(imap_param->pa_value); + if (value == NULL) { + free(name); + res = MAIL_ERROR_MEMORY; + goto free_parameters; + } + + param = mailmime_parameter_new(name, value); + if (param == NULL) { + free(value); + free(name); + res = MAIL_ERROR_MEMORY; + goto free_parameters; + } + + r = clist_append(parameters, param); + if (r != 0) { + mailmime_parameter_free(param); + res = MAIL_ERROR_MEMORY; + goto free_parameters; + } + } + } + + content = mailmime_content_new(mime_type, new_subtype, parameters); + if (content == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_parameters; + } + + * result = content; + + return MAIL_NO_ERROR; + + free_parameters: + clist_foreach(parameters, (clist_func) mailmime_parameter_free, NULL); + clist_free(parameters); + free_subtype: + free(new_subtype); + err: + return res; +} + +static int +imap_body_type_text_to_content_type(char * subtype, + struct mailimap_body_fld_param * + body_parameter, + struct mailmime_content ** result) +{ + struct mailmime_content * content; + struct mailmime_type * mime_type; + struct mailmime_discrete_type * discrete_type; + int r; + int res; + + discrete_type = NULL; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, + NULL); + if (discrete_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mime_type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, + discrete_type, NULL); + if (mime_type == NULL) { + mailmime_discrete_type_free(discrete_type); + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = imap_body_parameter_to_content(body_parameter, subtype, + mime_type, &content); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_type; + } + + * result = content; + + return MAIL_NO_ERROR; + + free_type: + mailmime_type_free(mime_type); + err: + return res; +} + + +static int +imap_body_type_msg_to_body(struct mailimap_body_type_msg * + imap_type_msg, + struct mailimap_body_ext_1part * + body_ext_1part, + struct mailmime ** result) +{ + struct mailmime * body; + struct mailmime * msg_body; + struct mailmime_fields * mime_fields; + struct mailmime_composite_type * composite_type; + struct mailmime_type * mime_type; + struct mailmime_content * content_type; + struct mailimf_fields * fields; + int r; + int res; + uint32_t mime_size; + + r = imap_body_fields_to_mime_fields(imap_type_msg->bd_fields, + body_ext_1part->bd_disposition, body_ext_1part->bd_language, + &mime_fields, &mime_size); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = imap_env_to_fields(imap_type_msg->bd_envelope, NULL, 0, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mime_fields; + } + + r = imap_body_to_body(imap_type_msg->bd_body, &msg_body); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_fields; + } + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, + NULL); + if (composite_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, + NULL, composite_type); + if (mime_type == NULL) { + mailmime_composite_type_free(composite_type); + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + r = imap_body_parameter_to_content(imap_type_msg->bd_fields->bd_parameter, + "rfc822", mime_type, &content_type); + if (r != MAIL_NO_ERROR) { + mailmime_type_free(mime_type); + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + body = mailmime_new(MAILMIME_MESSAGE, NULL, + mime_size, mime_fields, content_type, + NULL, NULL, NULL, NULL, fields, msg_body); + + if (body == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_content; + } + + * result = body; + + return MAIL_NO_ERROR; + + free_content: + mailmime_content_free(content_type); + free_fields: + mailimf_fields_free(fields); + free_mime_fields: + mailmime_fields_free(mime_fields); + err: + return res; +} + + +static int +imap_body_type_1part_to_body(struct mailimap_body_type_1part * + type_1part, + struct mailmime ** result) +{ + struct mailmime * body; + int r; + int res; + + body = NULL; + switch (type_1part->bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + r = imap_body_type_basic_to_body(type_1part->bd_data.bd_type_basic, + type_1part->bd_ext_1part, + &body); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + break; + case MAILIMAP_BODY_TYPE_1PART_MSG: + r = imap_body_type_msg_to_body(type_1part->bd_data.bd_type_msg, + type_1part->bd_ext_1part, + &body); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + break; + case MAILIMAP_BODY_TYPE_1PART_TEXT: + r = imap_body_type_text_to_body(type_1part->bd_data.bd_type_text, + type_1part->bd_ext_1part, + &body); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + break; + } + + * result = body; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +imap_body_type_mpart_to_body(struct mailimap_body_type_mpart * + type_mpart, + struct mailmime ** result) +{ + struct mailmime_fields * mime_fields; + struct mailmime_composite_type * composite_type; + struct mailmime_type * mime_type; + struct mailmime_content * content_type; + struct mailmime * body; + clistiter * cur; + clist * list; + int r; + int res; + uint32_t mime_size; + + r = imap_body_fields_to_mime_fields(NULL, + type_mpart->bd_ext_mpart->bd_disposition, + type_mpart->bd_ext_mpart->bd_language, + &mime_fields, &mime_size); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART, + NULL); + if (composite_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, + NULL, composite_type); + if (mime_type == NULL) { + mailmime_composite_type_free(composite_type); + res = MAIL_ERROR_MEMORY; + goto free_fields; + } + + r = imap_body_parameter_to_content(type_mpart->bd_ext_mpart->bd_parameter, + type_mpart->bd_media_subtype, + mime_type, &content_type); + if (r != MAIL_NO_ERROR) { + mailmime_type_free(mime_type); + res = r; + goto free_fields; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_content; + } + + for(cur = clist_begin(type_mpart->bd_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_body * imap_body; + struct mailmime * sub_body; + + imap_body = clist_content(cur); + + r = imap_body_to_body(imap_body, &sub_body); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, sub_body); + if (r != 0) { + mailmime_free(sub_body); + res = r; + goto free_list; + } + } + + body = mailmime_new(MAILMIME_MULTIPLE, NULL, + mime_size, mime_fields, content_type, + NULL, NULL, NULL, list, NULL, NULL); + + if (body == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + * result = body; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_free, NULL); + clist_free(list); + free_content: + mailmime_content_free(content_type); + free_fields: + mailmime_fields_free(mime_fields); + err: + return res; +} + + +int imap_body_to_body(struct mailimap_body * imap_body, + struct mailmime ** result) +{ + struct mailmime * body; + int r; + int res; + + body = NULL; + switch (imap_body->bd_type) { + case MAILIMAP_BODY_1PART: + r = imap_body_type_1part_to_body(imap_body->bd_data.bd_body_1part, &body); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMAP_BODY_MPART: + r = imap_body_type_mpart_to_body(imap_body->bd_data.bd_body_mpart, &body); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + default: + return MAIL_ERROR_INVAL; + } + + * result = body; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int imap_address_to_mailbox(struct mailimap_address * imap_addr, + struct mailimf_mailbox ** result) +{ + char * dsp_name; + char * addr; + struct mailimf_mailbox * mb; + int res; + + if (imap_addr->ad_personal_name == NULL) + dsp_name = NULL; + else { + dsp_name = strdup(imap_addr->ad_personal_name); + if (dsp_name == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + } + + if (imap_addr->ad_host_name == NULL) { + addr = strdup(imap_addr->ad_mailbox_name); + if (addr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_name; + } + } + else { + addr = malloc(strlen(imap_addr->ad_mailbox_name) + + strlen(imap_addr->ad_host_name) + 2); + if (addr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_name; + } + strcpy(addr, imap_addr->ad_mailbox_name); + strcat(addr, "@"); + strcat(addr, imap_addr->ad_host_name); + } + + mb = mailimf_mailbox_new(dsp_name, addr); + if (mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_addr; + } + + * result = mb; + + return MAIL_NO_ERROR; + + free_addr: + free(addr); + free_name: + free(dsp_name); + err: + return res; +} + +int imap_address_to_address(struct mailimap_address * imap_addr, + struct mailimf_address ** result) +{ + struct mailimf_address * addr; + struct mailimf_mailbox * mb; + int r; + int res; + + r = imap_address_to_mailbox(imap_addr, &mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + if (addr == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mb; + } + + * result = addr; + + return MAIL_NO_ERROR; + + free_mb: + mailimf_mailbox_free(mb); + err: + return res; +} + +int +imap_mailbox_list_to_mailbox_list(clist * imap_mailbox_list, + struct mailimf_mailbox_list ** result) +{ + clistiter * cur; + clist * list; + struct mailimf_mailbox_list * mb_list; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_address * imap_addr; + struct mailimf_mailbox * mb; + + imap_addr = clist_content(cur); + + if (imap_addr->ad_mailbox_name == NULL) + continue; + + r = imap_address_to_mailbox(imap_addr, &mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, mb); + if (r != 0) { + mailimf_mailbox_free(mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + mb_list = mailimf_mailbox_list_new(list); + if (mb_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = mb_list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(list); + err: + return MAIL_ERROR_MEMORY; +} + + + +/* + at exit, imap_mb_list will fall on the last element of the group, + where mailbox name will be NIL, so that imap_mailbox_list_to_address_list + can continue +*/ + +static int imap_mailbox_list_to_group(clist * imap_mb_list, clistiter ** iter, + struct mailimf_group ** result) +{ + clistiter * imap_mailbox_listiter; + clist * list; + struct mailimf_group * group; + struct mailimap_address * imap_addr; + char * group_name; + clistiter * cur; + struct mailimf_mailbox_list * mb_list; + int r; + int res; + + imap_mailbox_listiter = * iter; + + imap_addr = clist_content(imap_mailbox_listiter); + if (imap_addr->ad_mailbox_name == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + group_name = strdup(imap_addr->ad_mailbox_name); + if (group_name == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_group_name; + } + + for(cur = clist_next(imap_mailbox_listiter) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + imap_addr = clist_content(cur); + + if (imap_addr->ad_mailbox_name == NULL) { + break; + } + + r = imap_address_to_mailbox(imap_addr, &mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, mb); + if (r != 0) { + mailimf_mailbox_free(mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + mb_list = mailimf_mailbox_list_new(list); + if (mb_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + group = mailimf_group_new(group_name, mb_list); + if (group == NULL) { + mailimf_mailbox_list_free(mb_list); + res = MAIL_ERROR_MEMORY; + goto free_group_name; + } + + * result = group; + * iter = cur; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(list); + free_group_name: + free(group_name); + err: + return res; +} + +int +imap_mailbox_list_to_address_list(clist * imap_mailbox_list, + struct mailimf_address_list ** result) +{ + clistiter * cur; + clist * list; + struct mailimf_address_list * addr_list; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_address * imap_addr; + struct mailimf_address * addr; + + imap_addr = clist_content(cur); + + if (imap_addr->ad_mailbox_name == NULL) + continue; + + if ((imap_addr->ad_host_name == NULL) && + (imap_addr->ad_mailbox_name != NULL)) { + struct mailimf_group * group; + + group = NULL; + r = imap_mailbox_list_to_group(imap_mailbox_list, &cur, &group); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + addr = mailimf_address_new(MAILIMF_ADDRESS_GROUP, NULL, group); + if (addr == NULL) { + mailimf_group_free(group); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + else { + r = imap_address_to_address(imap_addr, &addr); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + } + + r = clist_append(list, addr); + if (r != 0) { + mailimf_address_free(addr); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + addr_list = mailimf_address_list_new(list); + if (addr_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = addr_list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_address_free, NULL); + clist_free(list); + err: + return res; +} + + +int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type) +{ + struct mailimap_fetch_att * fetch_att; + int res; + int r; + char * header; + clist * hdrlist; + struct mailimap_header_list * imap_hdrlist; + struct mailimap_section * section; + + fetch_att = mailimap_fetch_att_new_envelope(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + header = strdup("References"); + if (header == NULL) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + hdrlist = clist_new(); + if (hdrlist == NULL) { + free(header); + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = clist_append(hdrlist, header); + if (r < 0) { + free(header); + clist_foreach(hdrlist, (clist_func) free, NULL); + clist_free(hdrlist); + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + imap_hdrlist = mailimap_header_list_new(hdrlist); + if (imap_hdrlist == 0) { + clist_foreach(hdrlist, (clist_func) free, NULL); + clist_free(hdrlist); + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + section = mailimap_section_new_header_fields(imap_hdrlist); + if (section == NULL) { + mailimap_header_list_free(imap_hdrlist); + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_att = mailimap_fetch_att_new_body_peek_section(section); + if (fetch_att == NULL) { + mailimap_section_free(section); + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +int imap_env_to_fields(struct mailimap_envelope * env, + char * ref_str, size_t ref_size, + struct mailimf_fields ** result) +{ + clist * list; + struct mailimf_field * field; + int r; + struct mailimf_fields * fields; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (env->env_date != NULL) { + size_t cur_token; + struct mailimf_date_time * date_time; + + cur_token = 0; + r = mailimf_date_time_parse(env->env_date, strlen(env->env_date), + &cur_token, &date_time); + + if (r == MAILIMF_NO_ERROR) { + struct mailimf_orig_date * orig; + + orig = mailimf_orig_date_new(date_time); + if (orig == NULL) { + mailimf_date_time_free(date_time); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, orig, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_orig_date_free(orig); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_subject != NULL) { + char * subject; + struct mailimf_subject * subject_field; + + subject = strdup(env->env_subject); + if (subject == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + + subject_field = mailimf_subject_new(subject); + if (subject_field == NULL) { + free(subject); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_SUBJECT, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, subject_field, NULL, NULL, NULL); + if (field == NULL) { + mailimf_subject_free(subject_field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (env->env_from != NULL) { + if (env->env_from->frm_list != NULL) { + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + + r = imap_mailbox_list_to_mailbox_list(env->env_from->frm_list, &mb_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + from = mailimf_from_new(mb_list); + if (from == NULL) { + mailimf_mailbox_list_free(mb_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, from, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_from_free(from); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_sender != NULL) { + if (env->env_sender->snd_list != NULL) { + struct mailimf_sender * sender; + struct mailimf_mailbox * mb; + + r = imap_address_to_mailbox(clist_begin(env->env_sender->snd_list)->data, &mb); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + sender = mailimf_sender_new(mb); + if (sender == NULL) { + mailimf_mailbox_free(mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_SENDER, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + sender, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_sender_free(sender); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_reply_to != NULL) { + if (env->env_reply_to->rt_list != NULL) { + struct mailimf_address_list * addr_list; + struct mailimf_reply_to * reply_to; + + r = imap_mailbox_list_to_address_list(env->env_reply_to->rt_list, + &addr_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + reply_to = mailimf_reply_to_new(addr_list); + if (reply_to == NULL) { + mailimf_address_list_free(addr_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_REPLY_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, reply_to, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_reply_to_free(reply_to); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_to != NULL) { + if (env->env_to->to_list != NULL) { + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + + r = imap_mailbox_list_to_address_list(env->env_to->to_list, &addr_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + to = mailimf_to_new(addr_list); + if (to == NULL) { + mailimf_address_list_free(addr_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, to, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_to_free(to); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_cc != NULL) { + if (env->env_cc->cc_list != NULL) { + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + + r = imap_mailbox_list_to_address_list(env->env_cc->cc_list, &addr_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + cc = mailimf_cc_new(addr_list); + if (cc == NULL) { + mailimf_address_list_free(addr_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_CC, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, cc, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_cc_free(cc); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_bcc != NULL) { + if (env->env_bcc->bcc_list != NULL) { + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + + r = imap_mailbox_list_to_address_list(env->env_bcc->bcc_list, + &addr_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + bcc = mailimf_bcc_new(addr_list); + if (bcc == NULL) { + mailimf_address_list_free(addr_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_BCC, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, bcc, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_bcc_free(bcc); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + if (env->env_in_reply_to != NULL) { + struct mailimf_in_reply_to * in_reply_to; + size_t cur_token; + clist * msg_id_list; + + cur_token = 0; + r = mailimf_msg_id_list_parse(env->env_in_reply_to, + strlen(env->env_in_reply_to), &cur_token, &msg_id_list); + + switch (r) { + case MAILIMF_NO_ERROR: + in_reply_to = mailimf_in_reply_to_new(msg_id_list); + if (in_reply_to == NULL) { + clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL); + clist_free(msg_id_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_IN_REPLY_TO, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + in_reply_to, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_in_reply_to_free(in_reply_to); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + if (env->env_message_id != NULL) { + char * id; + struct mailimf_message_id * msg_id; + size_t cur_token; + + cur_token = 0; + r = mailimf_msg_id_parse(env->env_message_id, strlen(env->env_message_id), + &cur_token, &id); + switch (r) { + case MAILIMF_NO_ERROR: + + msg_id = mailimf_message_id_new(id); + if (msg_id == NULL) { + mailimf_msg_id_free(id); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, msg_id, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_message_id_free(msg_id); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r != 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + if (ref_str != NULL) { + struct mailimf_references * references; + size_t cur_token; + + cur_token = 0; + r = mailimf_references_parse(ref_str, ref_size, + &cur_token, &references); + switch (r) { + case MAILIMF_NO_ERROR: + field = mailimf_field_new(MAILIMF_FIELD_REFERENCES, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, + references, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_references_free(references); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = fields; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + err: + return res; +} + +int imap_get_msg_att_info(struct mailimap_msg_att * msg_att, + uint32_t * puid, + struct mailimap_envelope ** pimap_envelope, + char ** preferences, + size_t * pref_size, + struct mailimap_msg_att_dynamic ** patt_dyn, + struct mailimap_body ** pimap_body) +{ + clistiter * item_cur; + uint32_t uid; + struct mailimap_envelope * imap_envelope; + char * references; + size_t ref_size; + struct mailimap_msg_att_dynamic * att_dyn; + struct mailimap_body * imap_body; + + uid = 0; + imap_envelope = NULL; + references = NULL; + ref_size = 0; + att_dyn = NULL; + imap_body = NULL; + + for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ; + item_cur = clist_next(item_cur)) { + struct mailimap_msg_att_item * item; + + item = clist_content(item_cur); + + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ITEM_STATIC: + switch (item->att_data.att_static->att_type) { + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + if (imap_body == NULL) + imap_body = item->att_data.att_static->att_data.att_bodystructure; + break; + + case MAILIMAP_MSG_ATT_ENVELOPE: + if (imap_envelope == NULL) { + imap_envelope = item->att_data.att_static->att_data.att_env; + } + break; + + case MAILIMAP_MSG_ATT_UID: + uid = item->att_data.att_static->att_data.att_uid; + break; + + case MAILIMAP_MSG_ATT_BODY_SECTION: + if (references == NULL) { + references = item->att_data.att_static->att_data.att_body_section->sec_body_part; + ref_size = item->att_data.att_static->att_data.att_body_section->sec_length; + } + break; + } + break; + + case MAILIMAP_MSG_ATT_ITEM_DYNAMIC: + if (att_dyn == NULL) { + att_dyn = item->att_data.att_dyn; + } + break; + } + } + + if (puid != NULL) + * puid = uid; + if (pimap_envelope != NULL) + * pimap_envelope = imap_envelope; + if (preferences != NULL) + * preferences = references; + if (pref_size != NULL) + * pref_size = ref_size; + if (patt_dyn != NULL) + * patt_dyn = att_dyn; + if (pimap_body != NULL) + * pimap_body = imap_body; + + return MAIL_NO_ERROR; +} + +int +imap_fetch_result_to_envelop_list(clist * fetch_result, + struct mailmessage_list * env_list) +{ + clistiter * cur; + int r; + unsigned int i; + + i = 0; + + for(cur = clist_begin(fetch_result) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_msg_att * msg_att; + uint32_t uid; + struct mailimap_envelope * imap_envelope; + struct mailimap_msg_att_dynamic * att_dyn; + char * references; + size_t ref_size; + + msg_att = clist_content(cur); + + r = imap_get_msg_att_info(msg_att, &uid, &imap_envelope, + &references, &ref_size, + &att_dyn, + NULL); + + if (r == MAIL_NO_ERROR) { + if (uid != 0) { + while (i < carray_count(env_list->msg_tab)) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (uid == msg->msg_index) { + struct mailimf_fields * fields; + struct mail_flags * flags; + + if (imap_envelope != NULL) { + r = imap_env_to_fields(imap_envelope, + references, ref_size, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_fields = fields; + } + } + + if (att_dyn != NULL) { + r = imap_flags_to_flags(att_dyn, &flags); + + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + + i ++; + break; + } + + i ++; + } + } + } + } + + return MAIL_NO_ERROR; +} + + +int mailimf_date_time_to_imap_date(struct mailimf_date_time * date, + struct mailimap_date ** result) +{ + struct mailimap_date * imap_date; + + imap_date = mailimap_date_new(date->dt_day, date->dt_month, date->dt_year); + if (imap_date == NULL) + return MAIL_ERROR_MEMORY; + + * result = imap_date; + + return MAIL_NO_ERROR; +} + + +#if 0 +int mail_search_to_imap_search(struct mail_search_key * key, + struct mailimap_search_key ** result) +{ + struct mailimap_search_key * imap_key; + + char * bcc; + struct mailimap_date * before; + char * body; + char * cc; + char * from; + struct mailimap_date * on; + struct mailimap_date * since; + char * subject; + char * text; + char * to; + char * header_name; + char * header_value; + size_t larger; + struct mailimap_search_key * not; + struct mailimap_search_key * or1; + struct mailimap_search_key * or2; + size_t smaller; + clist * multiple; + int type; + clistiter * cur; + int r; + int res; + + bcc = NULL; + before = NULL; + body = NULL; + cc = NULL; + from = NULL; + on = NULL; + since = NULL; + subject = NULL; + text = NULL; + to = NULL; + header_name = NULL; + header_value = NULL; + not = NULL; + or1 = NULL; + or2 = NULL; + multiple = NULL; + larger = 0; + smaller = 0; + + switch (key->sk_type) { + case MAIL_SEARCH_KEY_ALL: + type = MAILIMAP_SEARCH_KEY_ALL; + break; + + case MAIL_SEARCH_KEY_ANSWERED: + type = MAILIMAP_SEARCH_KEY_ANSWERED; + break; + + case MAIL_SEARCH_KEY_BCC: + type = MAILIMAP_SEARCH_KEY_BCC; + bcc = strdup(key->sk_bcc); + if (bcc == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_BEFORE: + type = MAILIMAP_SEARCH_KEY_BEFORE; + r = mailimf_date_time_to_imap_date(key->sk_before, &before); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case MAIL_SEARCH_KEY_BODY: + type = MAILIMAP_SEARCH_KEY_BODY; + body = strdup(key->sk_body); + if (body == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_CC: + type = MAILIMAP_SEARCH_KEY_CC; + cc = strdup(key->sk_cc); + if (cc == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_DELETED: + type = MAILIMAP_SEARCH_KEY_DELETED; + break; + + case MAIL_SEARCH_KEY_FLAGGED: + type = MAILIMAP_SEARCH_KEY_FLAGGED; + break; + + case MAIL_SEARCH_KEY_FROM: + type = MAILIMAP_SEARCH_KEY_FROM; + from = strdup(key->sk_from); + if (from == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_NEW: + type = MAILIMAP_SEARCH_KEY_NEW; + break; + + case MAIL_SEARCH_KEY_OLD: + type = MAILIMAP_SEARCH_KEY_OLD; + break; + + case MAIL_SEARCH_KEY_ON: + type = MAILIMAP_SEARCH_KEY_ON; + r = mailimf_date_time_to_imap_date(key->sk_on, &on); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case MAIL_SEARCH_KEY_RECENT: + type = MAILIMAP_SEARCH_KEY_RECENT; + break; + + case MAIL_SEARCH_KEY_SEEN: + type = MAILIMAP_SEARCH_KEY_SEEN; + break; + + case MAIL_SEARCH_KEY_SINCE: + type = MAILIMAP_SEARCH_KEY_SINCE; + r = mailimf_date_time_to_imap_date(key->sk_since, &since); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case MAIL_SEARCH_KEY_SUBJECT: + type = MAILIMAP_SEARCH_KEY_SUBJECT; + subject = strdup(key->sk_subject); + if (subject == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_TEXT: + type = MAILIMAP_SEARCH_KEY_TEXT; + text = strdup(key->sk_text); + if (text == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_TO: + type = MAILIMAP_SEARCH_KEY_TO; + to = strdup(key->sk_to); + if (to == NULL) { + return MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_UNANSWERED: + type = MAILIMAP_SEARCH_KEY_UNANSWERED; + break; + + case MAIL_SEARCH_KEY_UNDELETED: + type = MAILIMAP_SEARCH_KEY_UNFLAGGED; + break; + + case MAIL_SEARCH_KEY_UNFLAGGED: + type = MAILIMAP_SEARCH_KEY_UNANSWERED; + break; + + case MAIL_SEARCH_KEY_UNSEEN: + type = MAILIMAP_SEARCH_KEY_UNSEEN; + break; + + case MAIL_SEARCH_KEY_HEADER: + type = MAILIMAP_SEARCH_KEY_HEADER; + header_name = strdup(key->sk_header_name); + if (header_name == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + header_value = strdup(key->sk_header_value); + if (header_value == NULL) { + free(header_name); + res = MAIL_ERROR_MEMORY; + goto err; + } + break; + + case MAIL_SEARCH_KEY_LARGER: + type = MAILIMAP_SEARCH_KEY_LARGER; + larger = key->sk_larger; + break; + + case MAIL_SEARCH_KEY_NOT: + type = MAILIMAP_SEARCH_KEY_NOT; + r = mail_search_to_imap_search(key->sk_not, ¬); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case MAIL_SEARCH_KEY_OR: + type = MAILIMAP_SEARCH_KEY_OR; + r = mail_search_to_imap_search(key->sk_or1, &or1); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + r = mail_search_to_imap_search(key->sk_or2, &or2); + if (r != MAIL_NO_ERROR) { + mailimap_search_key_free(or1); + res = r; + goto err; + } + break; + + case MAIL_SEARCH_KEY_SMALLER: + type = MAILIMAP_SEARCH_KEY_SMALLER; + smaller = key->sk_smaller; + break; + + case MAIL_SEARCH_KEY_MULTIPLE: + multiple = clist_new(); + if (multiple == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + type = MAILIMAP_SEARCH_KEY_MULTIPLE; + for(cur = clist_begin(key->sk_multiple) ; cur != NULL ; + cur = clist_next(cur)) { + struct mail_search_key * key_elt; + struct mailimap_search_key * imap_key_elt; + + key_elt = clist_content(cur); + r = mail_search_to_imap_search(key_elt, &imap_key_elt); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(multiple, imap_key_elt); + if (r != 0) { + mailimap_search_key_free(imap_key_elt); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + break; + + free_list: + clist_foreach(multiple, (clist_func) mailimap_search_key_free, NULL); + clist_free(multiple); + goto err; + + default: + return MAIL_ERROR_INVAL; + } + + imap_key = mailimap_search_key_new(type, bcc, before, body, cc, from, + NULL, on, since, subject, text, + to, NULL, header_name, + header_value, larger, not, or1, or2, + NULL, NULL, NULL, smaller, NULL, + NULL, multiple); + if (imap_key == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + * result = imap_key; + + return MAIL_NO_ERROR; + + free: + if (bcc != NULL) + free(bcc); + if (before != NULL) + mailimap_date_free(before); + if (body != NULL) + free(body); + if (cc != NULL) + free(cc); + if (from != NULL) + free(from); + if (on != NULL) + mailimap_date_free(on); + if (since != NULL) + mailimap_date_free(since); + if (subject != NULL) + free(subject); + if (text != NULL) + free(text); + if (to != NULL) + free(to); + if (header_name != NULL) + free(header_name); + if (header_value != NULL) + free(header_value); + if (not != NULL) + mailimap_search_key_free(not); + if (or1 != NULL) + mailimap_search_key_free(or1); + if (or2 != NULL) + mailimap_search_key_free(or2); + clist_foreach(multiple, (clist_func) mailimap_search_key_free, NULL); + clist_free(multiple); + err: + return res; +} +#endif + + +int msg_list_to_imap_set(clist * msg_list, + struct mailimap_set ** result) +{ + struct mailimap_set * imap_set; + clistiter * cur; + int previous_valid; + uint32_t first_seq; + uint32_t previous; + int r; + int res; + + imap_set = mailimap_set_new_empty(); + if (imap_set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + cur = clist_begin(msg_list); + previous_valid = FALSE; + first_seq = 0; + previous = 0; + while (1) { + uint32_t * pindex; + + if ((cur == NULL) && (previous_valid)) { + if (first_seq == previous) { + r = mailimap_set_add_single(imap_set, first_seq); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + } + else { + r = mailimap_set_add_interval(imap_set, first_seq, previous); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + } + break; + } + + pindex = clist_content(cur); + + if (!previous_valid) { + first_seq = * pindex; + previous_valid = TRUE; + previous = * pindex; + cur = clist_next(cur); + } + else { + if (* pindex != previous + 1) { + if (first_seq == previous) { + r = mailimap_set_add_single(imap_set, first_seq); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + } + else { + r = mailimap_set_add_interval(imap_set, first_seq, previous); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + } + previous_valid = FALSE; + } + else { + previous = * pindex; + cur = clist_next(cur); + } + } + } + + * result = imap_set; + + return MAIL_NO_ERROR; + + free: + mailimap_set_free(imap_set); + err: + return res; +} + + +static int +uid_list_to_env_list(clist * fetch_result, + struct mailmessage_list ** result, + mailsession * session, mailmessage_driver * driver) +{ + clistiter * cur; + struct mailmessage_list * env_list; + int r; + int res; + carray * tab; + unsigned int i; + mailmessage * msg; + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(fetch_result) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_msg_att * msg_att; + clistiter * item_cur; + uint32_t uid; + size_t size; + + msg_att = clist_content(cur); + + uid = 0; + size = 0; + for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ; + item_cur = clist_next(item_cur)) { + struct mailimap_msg_att_item * item; + + item = clist_content(item_cur); + + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ITEM_STATIC: + switch (item->att_data.att_static->att_type) { + case MAILIMAP_MSG_ATT_UID: + uid = item->att_data.att_static->att_data.att_uid; + break; + + case MAILIMAP_MSG_ATT_RFC822_SIZE: + size = item->att_data.att_static->att_data.att_rfc822_size; + break; + } + break; + } + } + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, driver, uid, size); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_msg; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_msg; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_msg: + mailmessage_free(msg); + free_list: + for(i = 0 ; i < carray_count(tab) ; i++) + mailmessage_free(carray_get(tab, i)); + err: + return res; +} + + +/* + MAILIMAP_FLAG_FETCH_RECENT, + MAILIMAP_FLAG_FETCH_OTHER + + MAILIMAP_FLAG_ANSWERED, + MAILIMAP_FLAG_FLAGGED, + MAILIMAP_FLAG_DELETED, + MAILIMAP_FLAG_SEEN, + MAILIMAP_FLAG_DRAFT, + MAILIMAP_FLAG_KEYWORD, + MAILIMAP_FLAG_EXTENSION +*/ + +static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn, + struct mail_flags ** result) +{ + struct mail_flags * flags; + clist * flag_list; + clistiter * cur; + + flags = mail_flags_new_empty(); + if (flags == NULL) + goto err; + flags->fl_flags = 0; + + flag_list = att_dyn->att_list; + if (flag_list != NULL) { + for(cur = clist_begin(flag_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_flag_fetch * flag_fetch; + + flag_fetch = clist_content(cur); + if (flag_fetch->fl_type == MAILIMAP_FLAG_FETCH_RECENT) + flags->fl_flags |= MAIL_FLAG_NEW; + else { + char * keyword; + int r; + + switch (flag_fetch->fl_flag->fl_type) { + case MAILIMAP_FLAG_ANSWERED: + flags->fl_flags |= MAIL_FLAG_ANSWERED; + break; + case MAILIMAP_FLAG_FLAGGED: + flags->fl_flags |= MAIL_FLAG_FLAGGED; + break; + case MAILIMAP_FLAG_DELETED: + flags->fl_flags |= MAIL_FLAG_DELETED; + break; + case MAILIMAP_FLAG_SEEN: + flags->fl_flags |= MAIL_FLAG_SEEN; + break; + case MAILIMAP_FLAG_DRAFT: + keyword = strdup("Draft"); + if (keyword == NULL) + goto free; + r = clist_append(flags->fl_extension, keyword); + if (r < 0) { + free(keyword); + goto free; + } + break; + case MAILIMAP_FLAG_KEYWORD: + if (strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, + "$Forwarded") == 0) { + flags->fl_flags |= MAIL_FLAG_FORWARDED; + } + else { + keyword = strdup(flag_fetch->fl_flag->fl_data.fl_keyword); + if (keyword == NULL) + goto free; + r = clist_append(flags->fl_extension, keyword); + if (r < 0) { + free(keyword); + goto free; + } + } + break; + case MAILIMAP_FLAG_EXTENSION: + /* do nothing */ + break; + } + } + } + /* + MAIL_FLAG_NEW was set for \Recent messages. + Correct this flag for \Seen messages by unsetting it. + */ + if ((flags->fl_flags & MAIL_FLAG_SEEN) && (flags->fl_flags & MAIL_FLAG_NEW)) { + flags->fl_flags &= ~MAIL_FLAG_NEW; + } + } + + * result = flags; + + return MAIL_NO_ERROR; + + free: + mail_flags_free(flags); + err: + return MAIL_ERROR_MEMORY; +} + +int imap_flags_to_imap_flags(struct mail_flags * flags, + struct mailimap_flag_list ** result) +{ + struct mailimap_flag * flag; + struct mailimap_flag_list * flag_list; + int res; + clistiter * cur; + int r; + + flag_list = mailimap_flag_list_new_empty(); + if (flag_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if ((flags->fl_flags & MAIL_FLAG_DELETED) != 0) { + flag = mailimap_flag_new_deleted(); + if (flag == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + + if ((flags->fl_flags & MAIL_FLAG_FLAGGED) != 0) { + flag = mailimap_flag_new_flagged(); + if (flag == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + + if ((flags->fl_flags & MAIL_FLAG_SEEN) != 0) { + flag = mailimap_flag_new_seen(); + if (flag == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + + if ((flags->fl_flags & MAIL_FLAG_ANSWERED) != 0) { + flag = mailimap_flag_new_answered(); + if (flag == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + + if ((flags->fl_flags & MAIL_FLAG_FORWARDED) != 0) { + char * flag_str; + + flag_str = strdup("$Forwarded"); + if (flag_str == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + flag = mailimap_flag_new_flag_keyword(flag_str); + if (flag == NULL) { + free(flag_str); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + + for(cur = clist_begin(flags->fl_extension) ; cur != NULL ; + cur = clist_next(cur)) { + char * flag_str; + + flag_str = clist_content(cur); + + if (strcasecmp(flag_str, "Draft") == 0) { + flag = mailimap_flag_new_draft(); + if (flag == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + else { + flag_str = strdup(flag_str); + if (flag_str == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + flag = mailimap_flag_new_flag_keyword(flag_str); + if (flag == NULL) { + free(flag_str); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + r = mailimap_flag_list_add(flag_list, flag); + if (r != MAILIMAP_NO_ERROR) { + mailimap_flag_free(flag); + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + } + } + + * result = flag_list; + + return MAIL_NO_ERROR; + + free_flag_list: + mailimap_flag_list_free(flag_list); + err: + return res; +} + +static int flags_to_imap_flags(struct mail_flags * flags, + struct mailimap_store_att_flags ** result) +{ + struct mailimap_flag_list * flag_list; + struct mailimap_store_att_flags * att_flags; + int res; + int r; + + r = imap_flags_to_imap_flags(flags, + &flag_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + att_flags = mailimap_store_att_flags_new_set_flags_silent(flag_list); + if (att_flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_flag_list; + } + + * result = att_flags; + + return MAIL_NO_ERROR; + + free_flag_list: + mailimap_flag_list_free(flag_list); + err: + return res; +} + + +static int +imap_fetch_result_to_flags(clist * fetch_result, uint32_t index, + struct mail_flags ** result) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(fetch_result) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_msg_att * msg_att; + clistiter * item_cur; + uint32_t uid; + struct mailimap_msg_att_dynamic * att_dyn; + + msg_att = clist_content(cur); + + uid = 0; + att_dyn = NULL; + + for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ; + item_cur = clist_next(item_cur)) { + struct mailimap_msg_att_item * item; + + item = clist_content(item_cur); + + if (item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) { + switch (item->att_data.att_static->att_type) { + case MAILIMAP_MSG_ATT_UID: + uid = item->att_data.att_static->att_data.att_uid; + break; + } + } + else if (item->att_type == MAILIMAP_MSG_ATT_ITEM_DYNAMIC) { + if (att_dyn == NULL) { + att_dyn = item->att_data.att_dyn; + } + } + } + + if (uid != 0) { + if (uid == index) { + struct mail_flags * flags; + + if (att_dyn != NULL) { + r = imap_flags_to_flags(att_dyn, &flags); + + if (r == MAIL_NO_ERROR) { + * result = flags; + return MAIL_NO_ERROR; + } + } + } + } + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} + + +int imap_fetch_flags(mailimap * imap, + uint32_t index, struct mail_flags ** result) +{ + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + int r; + int res; + clist * fetch_result; + struct mail_flags * flags; + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + fetch_att = mailimap_fetch_att_new_flags(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + set = mailimap_set_new_single(index); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + switch (r) { + case MAILIMAP_NO_ERROR: + break; + default: + return imap_error_to_mail_error(r); + } + + flags = NULL; + r = imap_fetch_result_to_flags(fetch_result, index, &flags); + mailimap_fetch_list_free(fetch_result); + + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + err: + return res; +} + +int imap_store_flags(mailimap * imap, uint32_t first, uint32_t last, + struct mail_flags * flags) +{ + struct mailimap_store_att_flags * att_flags; + struct mailimap_set * set; + int r; + int res; + + set = mailimap_set_new_interval(first, last); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = flags_to_imap_flags(flags, &att_flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_set; + } + + r = mailimap_uid_store(imap, set, att_flags); + if (r != MAILIMAP_NO_ERROR) { + res = imap_error_to_mail_error(r); + goto free_flag; + } + + mailimap_store_att_flags_free(att_flags); + mailimap_set_free(set); + + return MAIL_NO_ERROR; + + free_flag: + mailimap_store_att_flags_free(att_flags); + free_set: + mailimap_set_free(set); + err: + return res; +} + + + + +int imap_get_messages_list(mailimap * imap, + mailsession * session, mailmessage_driver * driver, + uint32_t first_index, + struct mailmessage_list ** result) +{ + struct mailmessage_list * env_list; + int r; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + clist * fetch_result; + int res; + + set = mailimap_set_new_interval(first_index, 0); + if (set == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fetch_type = mailimap_fetch_type_new_fetch_att_list_empty(); + if (fetch_type == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_set; + } + + fetch_att = mailimap_fetch_att_new_uid(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + fetch_att = mailimap_fetch_att_new_rfc822_size(); + if (fetch_att == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att); + if (r != MAILIMAP_NO_ERROR) { + mailimap_fetch_att_free(fetch_att); + res = MAIL_ERROR_MEMORY; + goto free_fetch_type; + } + + r = mailimap_uid_fetch(imap, set, + fetch_type, &fetch_result); + + mailimap_fetch_type_free(fetch_type); + mailimap_set_free(set); + + if (r != MAILIMAP_NO_ERROR) { + res = imap_error_to_mail_error(r); + goto err; + } + + env_list = NULL; + r = uid_list_to_env_list(fetch_result, &env_list, session, driver); + mailimap_fetch_list_free(fetch_result); + + * result = env_list; + + return MAIL_NO_ERROR; + + free_fetch_type: + mailimap_fetch_type_free(fetch_type); + free_set: + mailimap_set_free(set); + err: + return res; +} + +static void generate_key_from_message(char * key, size_t size, + mailmessage * msg_info, + int type) +{ + switch (type) { + case MAILIMAP_MSG_ATT_RFC822: + snprintf(key, size, "%s-rfc822", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_RFC822_HEADER: + snprintf(key, size, "%s-rfc822-header", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_RFC822_TEXT: + snprintf(key, size, "%s-rfc822-text", msg_info->msg_uid); + break; + case MAILIMAP_MSG_ATT_ENVELOPE: + snprintf(key, size, "%s-envelope", msg_info->msg_uid); + break; + } +} + +int +imapdriver_get_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, mailmessage * msg, + struct mailimf_fields ** result) +{ +#if 0 + mailsession * imap_session; +#endif + mailimap * imap; + int r; + struct mailimf_fields * fields; + int res; + char keyname[PATH_MAX]; + +#if 0 + imap_session = cached_session_get_ancestor(session); + imap = ((struct imap_session_state_data *) (imap_session->data))->session; +#endif + imap = cached_session_get_imap_session(session); + + generate_key_from_message(keyname, PATH_MAX, + msg, MAILIMAP_MSG_ATT_ENVELOPE); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + +err: + return res; +} + +int +imapdriver_write_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, mailmessage * msg, + struct mailimf_fields * fields) +{ + char keyname[PATH_MAX]; + int r; + int res; + + generate_key_from_message(keyname, PATH_MAX, + msg, MAILIMAP_MSG_ATT_ENVELOPE); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + +err: + return res; +} + Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_tools.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_tools.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,116 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_tools.h,v 1.8 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef IMAPDRIVER_TOOLS_H + +#define IMAPDRIVER_TOOLS_H + +#include "mailimap.h" +#include "mailmime.h" +#include "imapdriver_types.h" +#include "mail_cache_db.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int imap_list_to_list(clist * imap_list, struct mail_list ** result); + +int +section_to_imap_section(struct mailmime_section * section, int type, + struct mailimap_section ** result); + +int imap_get_msg_att_info(struct mailimap_msg_att * msg_att, + uint32_t * puid, + struct mailimap_envelope ** pimap_envelope, + char ** preferences, + size_t * pref_size, + struct mailimap_msg_att_dynamic ** patt_dyn, + struct mailimap_body ** pimap_body); + +int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type); + +int imap_env_to_fields(struct mailimap_envelope * env, + char * ref_str, size_t ref_size, + struct mailimf_fields ** result); + +int +imap_fetch_result_to_envelop_list(clist * fetch_result, + struct mailmessage_list * env_list); + +int imap_body_to_body(struct mailimap_body * imap_body, + struct mailmime ** result); + +#if 0 +int mail_search_to_imap_search(struct mail_search_key * key, + struct mailimap_search_key ** result); +#endif + +int msg_list_to_imap_set(clist * msg_list, + struct mailimap_set ** result); + +int imap_error_to_mail_error(int error); + +int imap_store_flags(mailimap * imap, uint32_t first, uint32_t last, + struct mail_flags * flags); + +int imap_fetch_flags(mailimap * imap, + uint32_t index, struct mail_flags ** result); + +int imap_get_messages_list(mailimap * imap, + mailsession * session, mailmessage_driver * driver, + uint32_t first_index, + struct mailmessage_list ** result); + +int +imapdriver_get_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, mailmessage * msg, + struct mailimf_fields ** result); + +int +imapdriver_write_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, mailmessage * msg, + struct mailimf_fields * fields); + +int imap_flags_to_imap_flags(struct mail_flags * flags, + struct mailimap_flag_list ** result); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapdriver_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,157 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapdriver_types.h,v 1.25 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef IMAPDRIVER_TYPES_H + +#define IMAPDRIVER_TYPES_H + +#include <libetpan/libetpan-config.h> + +#include <libetpan/mailimap.h> +#include <libetpan/maildriver_types.h> +#include <libetpan/generic_cache_types.h> +#include <libetpan/mailstorage_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* IMAP driver for session */ + +struct imap_session_state_data { + mailimap * imap_session; + char * imap_mailbox; + struct mail_flags_store * imap_flags_store; +}; + +enum { + IMAP_SECTION_MESSAGE, + IMAP_SECTION_HEADER, + IMAP_SECTION_MIME, + IMAP_SECTION_BODY +}; + +/* cached IMAP driver for session */ + +enum { + IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY = 1 +}; + +struct imap_cached_session_state_data { + mailsession * imap_ancestor; + char * imap_quoted_mb; + char imap_cache_directory[PATH_MAX]; + carray * imap_uid_list; + uint32_t imap_uidvalidity; +}; + + +/* IMAP storage */ + +/* + imap_mailstorage is the state data specific to the IMAP4rev1 storage. + + - servername this is the name of the IMAP4rev1 server + + - port is the port to connect to, on the server. + you give 0 to use the default port. + + - command, if non-NULL the command used to connect to the + server instead of allowing normal TCP connections to be used. + + - connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS or + CONNECTION_TYPE_COMMAND. + + - auth_type is the authenticate mechanism to use. + The value can be IMAP_AUTH_TYPE_PLAIN. + Other values are not yet implemented. + + - login is the login of the IMAP4rev1 account. + + - password is the password of the IMAP4rev1 account. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache +*/ + +struct imap_mailstorage { + char * imap_servername; + uint16_t imap_port; + char * imap_command; + int imap_connection_type; + + int imap_auth_type; + char * imap_login; /* deprecated */ + char * imap_password; /* deprecated */ + + int imap_cached; + char * imap_cache_directory; + + struct { + int sasl_enabled; + char * sasl_auth_type; + char * sasl_server_fqdn; + char * sasl_local_ip_port; + char * sasl_remote_ip_port; + char * sasl_login; + char * sasl_auth_name; + char * sasl_password; + char * sasl_realm; + } imap_sasl; +}; + +/* this is the type of IMAP4rev1 authentication */ + +enum { + IMAP_AUTH_TYPE_PLAIN, /* plain text authentication */ + IMAP_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */ + IMAP_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */ + IMAP_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */ + IMAP_AUTH_TYPE_SASL_PLAIN, /* SASL plain */ + IMAP_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */ + IMAP_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */ + IMAP_AUTH_TYPE_SASL_DIGEST_MD5 /* SASL digest MD5 */ +}; + + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapstorage.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapstorage.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,427 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapstorage.c,v 1.17 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "imapstorage.h" + +#include <stdlib.h> +#include <string.h> + +#include "mail.h" +#include "imapdriver.h" +#include "imapdriver_cached.h" +#include "mailstorage_tools.h" +#include "maildriver.h" + +/* imap storage */ + +#define IMAP_DEFAULT_PORT 143 +#define IMAPS_DEFAULT_PORT 993 + +static int imap_mailstorage_connect(struct mailstorage * storage); +static int +imap_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void imap_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver imap_mailstorage_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sto_name */ "imap", + /* sto_connect */ imap_mailstorage_connect, + /* sto_get_folder_session */ imap_mailstorage_get_folder_session, + /* sto_uninitialize */ imap_mailstorage_uninitialize, +#else + .sto_name = "imap", + .sto_connect = imap_mailstorage_connect, + .sto_get_folder_session = imap_mailstorage_get_folder_session, + .sto_uninitialize = imap_mailstorage_uninitialize, +#endif +}; + +LIBETPAN_EXPORT +int imap_mailstorage_init(struct mailstorage * storage, + const char * imap_servername, uint16_t imap_port, + const char * imap_command, + int imap_connection_type, int imap_auth_type, + const char * imap_login, const char * imap_password, + int imap_cached, const char * imap_cache_directory) +{ + struct imap_mailstorage * imap_storage; + int r; + + r = imap_mailstorage_init_sasl(storage, + imap_servername, imap_port, + imap_command, + imap_connection_type, + NULL, + NULL, + NULL, NULL, + imap_login, imap_login, + imap_password, NULL, + imap_cached, imap_cache_directory); + + if (r == MAIL_NO_ERROR) { + imap_storage = storage->sto_data; + imap_storage->imap_auth_type = imap_auth_type; + imap_storage->imap_login = imap_storage->imap_sasl.sasl_login; + imap_storage->imap_password = imap_storage->imap_sasl.sasl_password; + } + + return r; +} + +LIBETPAN_EXPORT +int imap_mailstorage_init_sasl(struct mailstorage * storage, + const char * imap_servername, uint16_t imap_port, + const char * imap_command, + int imap_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int imap_cached, const char * imap_cache_directory) +{ + struct imap_mailstorage * imap_storage; + + imap_storage = malloc(sizeof(* imap_storage)); + if (imap_storage == NULL) + goto err; + + imap_storage->imap_servername = strdup(imap_servername); + if (imap_storage->imap_servername == NULL) + goto free; + + imap_storage->imap_connection_type = imap_connection_type; + + if (imap_port == 0) { + switch (imap_connection_type) { + case CONNECTION_TYPE_PLAIN: + case CONNECTION_TYPE_TRY_STARTTLS: + case CONNECTION_TYPE_STARTTLS: + case CONNECTION_TYPE_COMMAND: + case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: + case CONNECTION_TYPE_COMMAND_STARTTLS: + imap_port = IMAP_DEFAULT_PORT; + break; + + case CONNECTION_TYPE_TLS: + case CONNECTION_TYPE_COMMAND_TLS: + imap_port = IMAPS_DEFAULT_PORT; + break; + } + } + + imap_storage->imap_port = imap_port; + + if (imap_command != NULL) { + imap_storage->imap_command = strdup(imap_command); + if (imap_storage->imap_command == NULL) + goto free_servername; + } + else + imap_storage->imap_command = NULL; + + imap_storage->imap_auth_type = IMAP_AUTH_TYPE_PLAIN; + + imap_storage->imap_sasl.sasl_enabled = (auth_type != NULL); + + if (auth_type != NULL) { + imap_storage->imap_sasl.sasl_auth_type = strdup(auth_type); + if (imap_storage->imap_sasl.sasl_auth_type == NULL) + goto free_command; + } + else + imap_storage->imap_sasl.sasl_auth_type = NULL; + + if (server_fqdn != NULL) { + imap_storage->imap_sasl.sasl_server_fqdn = strdup(server_fqdn); + if (imap_storage->imap_sasl.sasl_server_fqdn == NULL) + goto free_auth_type; + } + else + imap_storage->imap_sasl.sasl_server_fqdn = NULL; + + if (local_ip_port != NULL) { + imap_storage->imap_sasl.sasl_local_ip_port = strdup(local_ip_port); + if (imap_storage->imap_sasl.sasl_local_ip_port == NULL) + goto free_server_fqdn; + } + else + imap_storage->imap_sasl.sasl_local_ip_port = NULL; + + if (remote_ip_port != NULL) { + imap_storage->imap_sasl.sasl_remote_ip_port = strdup(remote_ip_port); + if (imap_storage->imap_sasl.sasl_remote_ip_port == NULL) + goto free_local_ip_port; + } + else + imap_storage->imap_sasl.sasl_remote_ip_port = NULL; + + if (login != NULL) { + imap_storage->imap_sasl.sasl_login = strdup(login); + if (imap_storage->imap_sasl.sasl_login == NULL) + goto free_remote_ip_port; + } + else + imap_storage->imap_sasl.sasl_login = NULL; + + if (auth_name != NULL) { + imap_storage->imap_sasl.sasl_auth_name = strdup(auth_name); + if (imap_storage->imap_sasl.sasl_auth_name == NULL) + goto free_login; + } + else + imap_storage->imap_sasl.sasl_auth_name = NULL; + + if (password != NULL) { + imap_storage->imap_sasl.sasl_password = strdup(password); + if (imap_storage->imap_sasl.sasl_password == NULL) + goto free_auth_name; + } + else + imap_storage->imap_sasl.sasl_password = NULL; + + if (realm != NULL) { + imap_storage->imap_sasl.sasl_realm = strdup(realm); + if (imap_storage->imap_sasl.sasl_realm == NULL) + goto free_password; + } + else + imap_storage->imap_sasl.sasl_realm = NULL; + + imap_storage->imap_cached = imap_cached; + + if (imap_cached && (imap_cache_directory != NULL)) { + imap_storage->imap_cache_directory = strdup(imap_cache_directory); + if (imap_storage->imap_cache_directory == NULL) + goto free_realm; + } + else { + imap_storage->imap_cached = FALSE; + imap_storage->imap_cache_directory = NULL; + } + + storage->sto_data = imap_storage; + storage->sto_driver = &imap_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_realm: + free(imap_storage->imap_sasl.sasl_realm); + free_password: + free(imap_storage->imap_sasl.sasl_password); + free_auth_name: + free(imap_storage->imap_sasl.sasl_auth_name); + free_login: + free(imap_storage->imap_sasl.sasl_login); + free_remote_ip_port: + free(imap_storage->imap_sasl.sasl_remote_ip_port); + free_local_ip_port: + free(imap_storage->imap_sasl.sasl_local_ip_port); + free_server_fqdn: + free(imap_storage->imap_sasl.sasl_server_fqdn); + free_auth_type: + free(imap_storage->imap_sasl.sasl_auth_type); + free_command: + free(imap_storage->imap_command); + free_servername: + free(imap_storage->imap_servername); + free: + free(imap_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void imap_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct imap_mailstorage * imap_storage; + + imap_storage = storage->sto_data; + + if (imap_storage->imap_cache_directory != NULL) + free(imap_storage->imap_cache_directory); + + free(imap_storage->imap_sasl.sasl_realm); + free(imap_storage->imap_sasl.sasl_password); + free(imap_storage->imap_sasl.sasl_auth_name); + free(imap_storage->imap_sasl.sasl_login); + free(imap_storage->imap_sasl.sasl_remote_ip_port); + free(imap_storage->imap_sasl.sasl_local_ip_port); + free(imap_storage->imap_sasl.sasl_server_fqdn); + free(imap_storage->imap_sasl.sasl_auth_type); + + if (imap_storage->imap_command != NULL) + free(imap_storage->imap_command); + free(imap_storage->imap_servername); + free(imap_storage); + + storage->sto_data = NULL; +} + +static int imap_connect(struct mailstorage * storage, + mailsession ** result) +{ + struct imap_mailstorage * imap_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + imap_storage = storage->sto_data; + + if (imap_storage->imap_cached) + driver = imap_cached_session_driver; + else + driver = imap_session_driver; + + r = mailstorage_generic_connect(driver, + imap_storage->imap_servername, + imap_storage->imap_port, + imap_storage->imap_command, + imap_storage->imap_connection_type, + IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY, + imap_storage->imap_cache_directory, + 0, NULL, + &session); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto err; + } + + if (imap_storage->imap_sasl.sasl_enabled) { + r = mailstorage_generic_auth_sasl(session, r, + imap_storage->imap_sasl.sasl_auth_type, + imap_storage->imap_sasl.sasl_server_fqdn, + imap_storage->imap_sasl.sasl_local_ip_port, + imap_storage->imap_sasl.sasl_remote_ip_port, + imap_storage->imap_sasl.sasl_login, + imap_storage->imap_sasl.sasl_auth_name, + imap_storage->imap_sasl.sasl_password, + imap_storage->imap_sasl.sasl_realm); + } + else { + r = mailstorage_generic_auth(session, r, + imap_storage->imap_auth_type, + imap_storage->imap_sasl.sasl_login, + imap_storage->imap_sasl.sasl_password); + } + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + * result = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int imap_mailstorage_connect(struct mailstorage * storage) +{ + mailsession * session; + int r; + int res; + + r = imap_connect(storage, &session); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailsession_select_folder(session, "INBOX"); + if (r != MAIL_NO_ERROR) { + mailsession_logout(session); + res = r; + goto err; + } + + storage->sto_session = session; + storage->sto_driver = &imap_mailstorage_driver; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +imap_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + mailsession * session; + int r; + int res; + + if (strcasecmp(pathname, "INBOX") == 0) { + session = storage->sto_session; + } + else { + r = imap_connect(storage, &session); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailsession_select_folder(session, pathname); + if (r != MAIL_NO_ERROR) { + mailsession_logout(session); + res = r; + goto free; + } + } + + * result = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapstorage.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/imap/imapstorage.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,104 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imapstorage.h,v 1.12 2006/06/02 15:44:29 smarinier Exp $ + */ + +#ifndef IMAPSTORAGE_H + +#define IMAPSTORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/imapdriver_types.h> + +/* + imap_mailstorage_init is the constructor for a IMAP4rev1 storage + + @param storage this is the storage to initialize. + + @param servername this is the name of the IMAP4rev1 server + + @param port is the port to connect to, on the server. + you give 0 to use the default port. + + @param command the command used to connect to the server instead of + allowing normal TCP connections to be used. + + @param connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS, + CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS, + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,. + + @param auth_type is the authenticate mechanism to use. + The value can be IMAP_AUTH_TYPE_PLAIN. + Other values are not yet implemented. + + @param login is the login of the IMAP4rev1 account. + + @param password is the password of the IMAP4rev1 account. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache +*/ + +LIBETPAN_EXPORT +int imap_mailstorage_init(struct mailstorage * storage, + const char * imap_servername, uint16_t imap_port, + const char * imap_command, + int imap_connection_type, int imap_auth_type, + const char * imap_login, const char * imap_password, + int imap_cached, const char * imap_cache_directory); + +LIBETPAN_EXPORT +int imap_mailstorage_init_sasl(struct mailstorage * storage, + const char * imap_servername, uint16_t imap_port, + const char * imap_command, + int imap_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int imap_cached, const char * imap_cache_directory); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,30 @@ +top_builddir = ../../../.. + +HEADERS = \ + maildirdriver.h \ + maildirdriver_cached.h \ + maildirdriver_cached_message.h \ + maildirdriver_message.h \ + maildirdriver_types.h \ + maildirstorage.h + + +SOURCES = \ + maildirdriver.c \ + maildirdriver_cached.c \ + maildirdriver_cached_message.c \ + maildirdriver_message.c \ + maildirdriver_tools.c \ + maildirstorage.c + + +TARGET = libmaildir +INCLUDES = -I../../interface \ + -I../../tools \ + -I$(srcdir)/low-level/maildir \ + -I$(srcdir)/low-level/mime \ + -I$(srcdir)/low-level/imf \ + -I$(srcdir)/data-types + + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,738 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver.c,v 1.15 2006/06/28 06:13:47 skunk Exp $ + */ + + +/* + flags directory MUST be kept so that we can have other flags + than standards +*/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "maildirdriver.h" + +#include <stdio.h> +#include <sys/types.h> +#ifdef _MSC_VER +# include "win_etpan.h" +#else +# include <dirent.h> +# include <unistd.h> +# include <sys/mman.h> +#endif +#include <sys/stat.h> +#include <ctype.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> + +#include "maildir.h" +#include "maildriver_tools.h" +#include "maildirdriver_message.h" +#include "maildirdriver_tools.h" +#include "mailmessage.h" +#include "generic_cache.h" + +static int initialize(mailsession * session); + +static void uninitialize(mailsession * session); + +static int connect_path(mailsession * session, const char * path); + +static int logout(mailsession * session); + +static int expunge_folder(mailsession * session); + +static int status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int recent_number(mailsession * session, const char * mb, + uint32_t * result); + +static int unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +static int messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int append_message(mailsession * session, + const char * message, size_t size); + +static int append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int check_folder(mailsession * session); + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + +static mailsession_driver local_maildir_session_driver = { + +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + + /* sess_name */ "maildir", + + /* sess_initialize */ initialize, + /* sess_uninitialize */ uninitialize, + + /* sess_parameters */ NULL, + + /* sess_connect_stream */ NULL, + /* sess_connect_path */ connect_path, + /* sess_starttls */ NULL, + /* sess_login */ NULL, + /* sess_logout */ logout, + /* sess_noop */ NULL, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ check_folder, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ NULL, + /* sess_expunge_folder */ expunge_folder, + /* sess_status_folder */ status_folder, + /* sess_messages_number */ messages_number, + /* sess_recent_number */ recent_number, + /* sess_unseen_number */ unseen_number, + /* sess_list_folders */ NULL, + /* sess_lsub_folders */ NULL, + /* sess_subscribe_folder */ NULL, + /* sess_unsubscribe_folder */ NULL, + + /* sess_append_message */ append_message, + /* sess_append_message_flags */ append_message_flags, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ NULL, + /* sess_get_message_by_uid */ get_message_by_uid, + + /* sess_get_messages_list */ get_messages_list, + /* sess_get_envelopes_list */ get_envelopes_list, + /* sess_remove_message */ NULL, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL, + +#else + .sess_name = "maildir", + + .sess_initialize = initialize, + .sess_uninitialize = uninitialize, + + .sess_parameters = NULL, + + .sess_connect_stream = NULL, + .sess_connect_path = connect_path, + .sess_starttls = NULL, + .sess_login = NULL, + .sess_logout = logout, + .sess_noop = NULL, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = check_folder, + .sess_examine_folder = NULL, + .sess_select_folder = NULL, + .sess_expunge_folder = expunge_folder, + .sess_status_folder = status_folder, + .sess_messages_number = messages_number, + .sess_recent_number = recent_number, + .sess_unseen_number = unseen_number, + .sess_list_folders = NULL, + .sess_lsub_folders = NULL, + .sess_subscribe_folder = NULL, + .sess_unsubscribe_folder = NULL, + + .sess_append_message = append_message, + .sess_append_message_flags = append_message_flags, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = get_messages_list, + .sess_get_envelopes_list = get_envelopes_list, + .sess_remove_message = NULL, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = NULL, + .sess_get_message_by_uid = get_message_by_uid, + .sess_login_sasl = NULL, + +#endif +}; + +mailsession_driver * maildir_session_driver = &local_maildir_session_driver; + + +static int flags_store_process(struct maildir * md, + struct mail_flags_store * flags_store); + + +static inline struct maildir_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static struct maildir * get_maildir_session(mailsession * session) +{ + return get_data(session)->md_session; +} + +static int initialize(mailsession * session) +{ + struct maildir_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->md_session = NULL; + + data->md_flags_store = mail_flags_store_new(); + if (data->md_flags_store == NULL) + goto free; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void uninitialize(mailsession * session) +{ + struct maildir_session_state_data * data; + + data = get_data(session); + + if (data->md_session != NULL) + flags_store_process(data->md_session, data->md_flags_store); + + mail_flags_store_free(data->md_flags_store); + if (data->md_session != NULL) + maildir_free(data->md_session); + + free(data); + + session->sess_data = NULL; +} + + +static int connect_path(mailsession * session, const char * path) +{ + struct maildir * md; + int res; + int r; + + if (get_maildir_session(session) != NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + md = maildir_new(path); + if (md == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto free; + } + + get_data(session)->md_session = md; + + return MAIL_NO_ERROR; + + free: + maildir_free(md); + err: + return res; +} + +static int logout(mailsession * session) +{ + struct maildir * md; + + check_folder(session); + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + maildir_free(md); + get_data(session)->md_session = NULL; + + return MAIL_NO_ERROR; +} + +/* folders operations */ + +static int status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int r; + struct maildir * md; + unsigned int i; + uint32_t messages; + uint32_t recent; + uint32_t unseen; + + check_folder(session); + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) + return maildirdriver_maildir_error_to_mail_error(r); + + messages = 0; + recent = 0; + unseen = 0; + for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i ++) { + struct maildir_msg * msg; + + msg = carray_get(md->mdir_msg_list, i); + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + recent ++; + if ((msg->msg_flags & MAILDIR_FLAG_SEEN) == 0) + unseen ++; + messages ++; + } + + * result_messages = messages; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; +} + +static int messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + struct maildir * md; + int r; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) + return maildirdriver_maildir_error_to_mail_error(r); + + * result = carray_count(md->mdir_msg_list); + + return MAIL_NO_ERROR; +} + +static int unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +static int recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + + +/* messages operations */ + +static int append_message(mailsession * session, + const char * message, size_t size) +{ +#if 0 + struct maildir * md; + int r; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_message_add(md, message, size); + if (r != MAILDIR_NO_ERROR) + return maildirdriver_maildir_error_to_mail_error(r); + + return MAIL_NO_ERROR; +#endif + + return append_message_flags(session, message, size, NULL); +} + +static int append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + struct maildir * md; + int r; + char uid[PATH_MAX]; + struct maildir_msg * md_msg; + chashdatum key; + chashdatum value; + uint32_t md_flags; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_message_add_uid(md, message, size, + uid, sizeof(uid)); + if (r != MAILDIR_NO_ERROR) + return maildirdriver_maildir_error_to_mail_error(r); + + if (flags == NULL) + goto exit; + + key.data = uid; + key.len = strlen(uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + goto exit; + + md_msg = value.data; + + md_flags = maildirdriver_flags_to_maildir_flags(flags->fl_flags); + + r = maildir_message_change_flags(md, uid, md_flags); + if (r != MAILDIR_NO_ERROR) + goto exit; + + return MAIL_NO_ERROR; + + exit: + return MAIL_NO_ERROR; +} + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct maildir * md; + int r; + struct mailmessage_list * env_list; + int res; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + r = maildir_get_messages_list(session, md, + maildir_message_driver, &env_list); + if (r != MAILDIR_NO_ERROR) { + res = r; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + mailmessage_list_free(env_list); + err: + return res; +} + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + struct maildir * md; + unsigned int i; + int res; + + check_folder(session); + + md = get_maildir_session(session); + if (md == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + r = maildriver_generic_get_envelopes_list(session, env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i++) { + struct maildir_msg * md_msg; + mailmessage * msg; + uint32_t driver_flags; + clist * ext; + chashdatum key; + chashdatum value; + + msg = carray_get(env_list->msg_tab, i); + + key.data = msg->msg_uid; + key.len = strlen(msg->msg_uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + continue; + + md_msg = value.data; + + driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags); + + if (msg->msg_flags == NULL) { + ext = clist_new(); + if (ext == NULL) { + res = MAIL_ERROR_MEMORY; + continue; + } + + msg->msg_flags = mail_flags_new(driver_flags, ext); + if (msg->msg_flags == NULL) { + clist_free(ext); + res = MAIL_ERROR_MEMORY; + continue; + } + + if ((md_msg->msg_flags & MAILDIR_FLAG_NEW) != 0) { + mail_flags_store_set(get_data(session)->md_flags_store, msg); + } + } + else { + msg->msg_flags->fl_flags &= MAIL_FLAG_FORWARDED; + msg->msg_flags->fl_flags |= driver_flags; + } + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +static int expunge_folder(mailsession * session) +{ + unsigned int i; + int r; + int res; + struct maildir * md; + + check_folder(session); + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i++) { + struct maildir_msg * md_msg; + + md_msg = carray_get(md->mdir_msg_list, i); + + if ((md_msg->msg_flags & MAILDIR_FLAG_TRASHED) != 0) + maildir_message_remove(md, md_msg->msg_uid); + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +static int flags_store_process(struct maildir * md, + struct mail_flags_store * flags_store) +{ + unsigned int i; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + uint32_t md_flags; + + msg = carray_get(flags_store->fls_tab, i); + md_flags = maildirdriver_flags_to_maildir_flags(msg->msg_flags->fl_flags); + md_flags &= ~MAILDIR_FLAG_NEW; + + maildir_message_change_flags(md, msg->msg_uid, md_flags); + } + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; +} + + + +static int check_folder(mailsession * session) +{ + struct mail_flags_store * flags_store; + struct maildir_session_state_data * data; + struct maildir * md; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + data = get_data(session); + flags_store = data->md_flags_store; + + return flags_store_process(md, flags_store); +} + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result) +{ + int r; + struct maildir * md; + int res; + mailmessage * msg; + char * msg_filename; + struct stat stat_info; + + md = get_maildir_session(session); + + /* update maildir data */ + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + msg_filename = maildir_message_get(md, uid); + if (msg_filename == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + r = stat(msg_filename, &stat_info); + free(msg_filename); + if (r < 0) { + res = MAIL_ERROR_INVAL; + goto err; + } + + /* create message */ + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_init(msg, session, maildir_message_driver, + 0, stat_info.st_size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto err; + } + + msg->msg_uid = strdup(uid); + if (msg->msg_uid == NULL) { + mailmessage_free(msg); + res = r; + goto err; + } + + * result = msg; + + return MAIL_NO_ERROR; + + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver.h,v 1.4 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_H + +#define MAILDIRDRIVER_H + +#include <libetpan/maildriver.h> +#include <libetpan/maildirdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * maildir_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_cached.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_cached.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1216 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_cached.c,v 1.17 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "maildirdriver.h" + +#include <stdio.h> +#include <sys/types.h> +#ifndef _MSC_VER +# include <dirent.h> +# include <unistd.h> +# include <sys/mman.h> +#endif +#include <sys/stat.h> +#include <ctype.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> + +#include "mail.h" +#include "maildir.h" +#include "maildriver_tools.h" +#include "maildirdriver_tools.h" +#include "maildirdriver_cached_message.h" +#include "mailmessage.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mail_cache_db.h" +#include "libetpan-config.h" + +static int initialize(mailsession * session); + +static void uninitialize(mailsession * session); + +static int parameters(mailsession * session, + int id, void * value); + +static int connect_path(mailsession * session, const char * path); + +static int logout(mailsession * session); + +static int expunge_folder(mailsession * session); + +static int status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int recent_number(mailsession * session, const char * mb, + uint32_t * result); + +static int unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +static int messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int append_message(mailsession * session, + const char * message, size_t size); + +static int append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int check_folder(mailsession * session); + +static int get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + +static mailsession_driver local_maildir_cached_session_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sess_name */ "maildir-cached", + + /* sess_initialize */ initialize, + /* sess_uninitialize */ uninitialize, + + /* sess_parameters */ parameters, + + /* sess_connect_stream */ NULL, + /* sess_connect_path */ connect_path, + /* sess_starttls */ NULL, + /* sess_login */ NULL, + /* sess_logout */ logout, + /* sess_noop */ NULL, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ check_folder, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ NULL, + /* sess_expunge_folder */ expunge_folder, + /* sess_status_folder */ status_folder, + /* sess_messages_number */ messages_number, + /* sess_recent_number */ recent_number, + /* sess_unseen_number */ unseen_number, + /* sess_list_folders */ NULL, + /* sess_lsub_folders */ NULL, + /* sess_subscribe_folder */ NULL, + /* sess_unsubscribe_folder */ NULL, + + /* sess_append_message */ append_message, + /* sess_append_message_flags */ append_message_flags, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ get_message, + /* sess_get_message_by_uid */ get_message_by_uid, + + /* sess_get_messages_list */ get_messages_list, + /* sess_get_envelopes_list */ get_envelopes_list, + /* sess_remove_message */ NULL, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL, + +#else + .sess_name = "maildir-cached", + + .sess_initialize = initialize, + .sess_uninitialize = uninitialize, + + .sess_parameters = parameters, + + .sess_connect_stream = NULL, + .sess_connect_path = connect_path, + .sess_starttls = NULL, + .sess_login = NULL, + .sess_logout = logout, + .sess_noop = NULL, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = check_folder, + .sess_examine_folder = NULL, + .sess_select_folder = NULL, + .sess_expunge_folder = expunge_folder, + .sess_status_folder = status_folder, + .sess_messages_number = messages_number, + .sess_recent_number = recent_number, + .sess_unseen_number = unseen_number, + .sess_list_folders = NULL, + .sess_lsub_folders = NULL, + .sess_subscribe_folder = NULL, + .sess_unsubscribe_folder = NULL, + + .sess_append_message = append_message, + .sess_append_message_flags = append_message_flags, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = get_messages_list, + .sess_get_envelopes_list = get_envelopes_list, + .sess_remove_message = NULL, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = get_message, + .sess_get_message_by_uid = get_message_by_uid, + .sess_login_sasl = NULL, +#endif +}; + +mailsession_driver * maildir_cached_session_driver = +&local_maildir_cached_session_driver; + + +static inline struct maildir_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->md_ancestor; +} + +static inline struct maildir_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + + +static struct maildir * get_maildir_session(mailsession * session) +{ + return get_ancestor_data(session)->md_session; +} + +static int initialize(mailsession * session) +{ + struct maildir_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->md_ancestor = mailsession_new(maildir_session_driver); + if (data->md_ancestor == NULL) + goto free; + + data->md_flags_store = mail_flags_store_new(); + if (data->md_flags_store == NULL) + goto free_session; + + data->md_quoted_mb = NULL; + data->md_cache_directory[0] = '\0'; + data->md_flags_directory[0] = '\0'; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_session: + mailsession_free(data->md_ancestor); + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void +free_quoted_mb(struct maildir_cached_session_state_data * maildir_cached_data) +{ + if (maildir_cached_data->md_quoted_mb != NULL) { + free(maildir_cached_data->md_quoted_mb); + maildir_cached_data->md_quoted_mb = NULL; + } +} + +static int +write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, struct mail_flags * flags); + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + +static int flags_store_process(char * flags_directory, char * quoted_mb, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + if (quoted_mb == NULL) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + flags_directory, MAIL_DIR_SEPARATOR, quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + if (r != MAIL_NO_ERROR) { + /* ignore errors */ + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void uninitialize(mailsession * session) +{ + struct maildir_cached_session_state_data * data; + + data = get_cached_data(session); + + flags_store_process(data->md_flags_directory, + data->md_quoted_mb, + data->md_flags_store); + + mail_flags_store_free(data->md_flags_store); + mailsession_free(data->md_ancestor); + free_quoted_mb(data); + free(data); + + session->sess_data = data; +} + + +static int parameters(mailsession * session, + int id, void * value) +{ + struct maildir_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + switch (id) { + case MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(data->md_cache_directory, value, PATH_MAX); + data->md_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->md_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(data->md_flags_directory, value, PATH_MAX); + data->md_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->md_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + default: + return mailsession_parameters(data->md_ancestor, id, value); + } +} + + +static int get_cache_folder(mailsession * session, char ** result) +{ + struct maildir * md; + char * quoted_mb; + int res; + int r; + char key[PATH_MAX]; + struct maildir_cached_session_state_data * data; + + md = get_maildir_session(session); + data = get_cached_data(session); + + quoted_mb = maildriver_quote_mailbox(md->mdir_path); + if (quoted_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(key, PATH_MAX, "%s/%s", data->md_cache_directory, quoted_mb); + r = generic_cache_create_dir(key); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_quoted_mb; + } + + snprintf(key, PATH_MAX, "%s/%s", data->md_flags_directory, quoted_mb); + r = generic_cache_create_dir(key); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_quoted_mb; + } + + * result = quoted_mb; + + return MAIL_NO_ERROR; + + free_quoted_mb: + free(quoted_mb); + err: + return res; +} + + +static int connect_path(mailsession * session, const char * path) +{ + int r; + int res; + char * quoted_mb; + + r = mailsession_connect_path(get_ancestor(session), path); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + quoted_mb = NULL; + r = get_cache_folder(session, "ed_mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto logout; + } + + get_cached_data(session)->md_quoted_mb = quoted_mb; + + return MAILDIR_NO_ERROR; + + logout: + mailsession_logout(get_ancestor(session)); + err: + return res; +} + +static int logout(mailsession * session) +{ + struct maildir_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + flags_store_process(data->md_flags_directory, + data->md_quoted_mb, data->md_flags_store); + + r = mailsession_logout(get_ancestor(session)); + if (r != MAIL_NO_ERROR) + return r; + + free_quoted_mb(get_cached_data(session)); + + return MAIL_NO_ERROR; +} + +static int status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + return mailsession_status_folder(get_ancestor(session), mb, + result_messages, result_recent, result_unseen); +} + +static int messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + return mailsession_messages_number(get_ancestor(session), mb, result); +} + +static int unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + return mailsession_unseen_number(get_ancestor(session), mb, result); +} + +static int recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + return mailsession_recent_number(get_ancestor(session), mb, result); +} + + +static int append_message(mailsession * session, + const char * message, size_t size) +{ +#if 0 + return mailsession_append_message(get_ancestor(session), message, size); +#endif + return append_message_flags(session, message, size, NULL); +} + +static int append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + struct maildir * md; + int r; + char uid[PATH_MAX]; + struct maildir_msg * md_msg; + chashdatum key; + chashdatum value; + uint32_t md_flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + MMAPString * mmapstr; + struct maildir_cached_session_state_data * data; + + md = get_maildir_session(session); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + r = maildir_message_add_uid(md, message, size, + uid, sizeof(uid)); + if (r != MAILDIR_NO_ERROR) + return maildirdriver_maildir_error_to_mail_error(r); + + if (flags == NULL) + goto exit; + + data = get_cached_data(session); + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) + goto exit; + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) + goto close_db_flags; + + r = write_cached_flags(cache_db_flags, mmapstr, + uid, flags); + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + if (r != MAIL_NO_ERROR) + goto exit; + + key.data = uid; + key.len = strlen(uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + goto exit; + + md_msg = value.data; + + md_flags = maildirdriver_flags_to_maildir_flags(flags->fl_flags); + + r = maildir_message_change_flags(md, uid, md_flags); + if (r != MAILDIR_NO_ERROR) + goto exit; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + exit: + return MAIL_NO_ERROR; +} + +#define UID_NAME "uid.db" + +static int uid_clean_up(struct mail_cache_db * uid_db, + struct mailmessage_list * env_list) +{ + chash * hash_exist; + int res; + int r; + unsigned int i; + chashdatum key; + chashdatum value; + char key_str[PATH_MAX]; + + /* flush cache */ + + hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (hash_exist == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + value.data = NULL; + value.len = 0; + + key.data = "max-uid"; + key.len = strlen("max-uid"); + r = chash_set(hash_exist, &key, &value, NULL); + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + value.data = NULL; + value.len = 0; + + key.data = msg->msg_uid; + key.len = strlen(msg->msg_uid); + r = chash_set(hash_exist, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + snprintf(key_str, sizeof(key_str), "uid-%lu", + (unsigned long) msg->msg_index); + key.data = key_str; + key.len = strlen(key_str); + r = chash_set(hash_exist, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + } + + mail_cache_db_clean_up(uid_db, hash_exist); + + chash_free(hash_exist); + + return MAIL_NO_ERROR; + + free: + chash_free(hash_exist); + err: + return res; +} + +static int get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct maildir * md; + int r; + struct mailmessage_list * env_list; + int res; + uint32_t max_uid; + char filename[PATH_MAX]; + struct mail_cache_db * uid_db; + void * value; + size_t value_len; + unsigned long i; + struct maildir_cached_session_state_data * data; + char key[PATH_MAX]; + + data = get_cached_data(session); + + md = get_maildir_session(session); + if (md == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + check_folder(session); + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + r = maildir_get_messages_list(session, md, + maildir_cached_message_driver, &env_list); + if (r != MAILDIR_NO_ERROR) { + res = r; + goto err; + } + + /* read/write DB */ + + snprintf(filename, sizeof(filename), "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, UID_NAME); + + r = mail_cache_db_open_lock(filename, &uid_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + max_uid = 0; + r = mail_cache_db_get(uid_db, "max-uid", sizeof("max-uid") - 1, + &value, &value_len); + if (r == 0) { + memcpy(&max_uid, value, sizeof(max_uid)); + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + uint32_t index; + + msg = carray_get(env_list->msg_tab, i); + + r = mail_cache_db_get(uid_db, msg->msg_uid, + strlen(msg->msg_uid), &value, &value_len); + if (r < 0) { + max_uid ++; + msg->msg_index = max_uid; + mail_cache_db_put(uid_db, msg->msg_uid, + strlen(msg->msg_uid), &msg->msg_index, sizeof(msg->msg_index)); + + snprintf(key, sizeof(key), "uid-%lu", (unsigned long) msg->msg_index); + mail_cache_db_put(uid_db, key, strlen(key), + msg->msg_uid, strlen(msg->msg_uid)); + } + else { + memcpy(&index, value, sizeof(index)); + msg->msg_index = index; + } + } + + mail_cache_db_put(uid_db, "max-uid", sizeof("max-uid") - 1, + &max_uid, sizeof(max_uid)); + + uid_clean_up(uid_db, env_list); + + mail_cache_db_close_unlock(filename, uid_db); + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + mailmessage_list_free(env_list); + err: + return res; +} + +static int +get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + char * uid, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, char * uid, + struct mailimf_fields ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mailimf_fields * fields; + int res; + + snprintf(keyname, PATH_MAX, "%s-envelope", uid); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, char * uid, + struct mailimf_fields * fields) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-envelope", uid); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +static int get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + int res; + struct maildir_cached_session_state_data * data; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + + data = get_cached_data(session); + + flags_store_process(data->md_flags_directory, + data->md_quoted_mb, data->md_flags_store); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename_env, PATH_MAX, "%s%c%s%c%s", + data->md_cache_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, ENV_NAME); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i++) { + mailmessage * msg; + struct mailimf_fields * fields; + struct mail_flags * flags; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, session, + msg->msg_uid, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + + if (msg->msg_flags == NULL) { + r = get_cached_flags(cache_db_flags, mmapstr, + session, msg->msg_uid, &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + /* msg->index is the numerical UID of the message */ + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_uid, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int expunge_folder(mailsession * session) +{ + return mailsession_expunge_folder(get_ancestor(session)); +} + +static int check_folder(mailsession * session) +{ + struct maildir_cached_session_state_data * data; + + data = get_cached_data(session); + + flags_store_process(data->md_flags_directory, + data->md_quoted_mb, data->md_flags_store); + + return mailsession_check_folder(get_ancestor(session)); +} + +static int get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + struct maildir * md; + int res; + mailmessage * msg; + char filename[PATH_MAX]; + struct mail_cache_db * uid_db; + char * msg_filename; + struct stat stat_info; + char key_str[PATH_MAX]; + void * value; + size_t value_len; + char uid[PATH_MAX]; + struct maildir_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + md = get_maildir_session(session); + + /* a get_messages_list() should have been done once before */ + + /* read DB */ + + snprintf(filename, sizeof(filename), "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, UID_NAME); + + r = mail_cache_db_open_lock(filename, &uid_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(key_str, sizeof(key_str), "uid-%lu", (unsigned long) num); + + r = mail_cache_db_get(uid_db, key_str, strlen(key_str), &value, &value_len); + if (r < 0) { + res = MAIL_ERROR_INVAL; + goto close_db; + } + + if (value_len >= PATH_MAX) { + res = MAIL_ERROR_INVAL; + goto close_db; + } + + memcpy(uid, value, value_len); + uid[value_len] = '\0'; + + mail_cache_db_close_unlock(filename, uid_db); + + /* update maildir data */ + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + msg_filename = maildir_message_get(md, uid); + if (msg_filename == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + r = stat(msg_filename, &stat_info); + free(msg_filename); + if (r < 0) { + res = MAIL_ERROR_INVAL; + goto err; + } + + /* create message */ + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_init(msg, session, maildir_cached_message_driver, + num, stat_info.st_size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto err; + } + + msg->msg_uid = strdup(uid); + if (msg->msg_uid == NULL) { + mailmessage_free(msg); + res = r; + goto err; + } + + * result = msg; + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(filename, uid_db); + err: + return res; +} + + +static int get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result) +{ + int r; + struct maildir * md; + int res; + mailmessage * msg; + char filename[PATH_MAX]; + struct mail_cache_db * uid_db; + char * msg_filename; + struct stat stat_info; + void * value; + size_t value_len; + struct maildir_cached_session_state_data * data; + uint32_t index; + + data = get_cached_data(session); + + md = get_maildir_session(session); + + /* a get_messages_list() should have been done once before */ + + /* read DB */ + + snprintf(filename, sizeof(filename), "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, UID_NAME); + + r = mail_cache_db_open_lock(filename, &uid_db); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mail_cache_db_get(uid_db, uid, strlen(uid), &value, &value_len); + if (r < 0) { + res = MAIL_ERROR_INVAL; + goto close_db; + } + + memcpy(&index, value, sizeof(index)); + + mail_cache_db_close_unlock(filename, uid_db); + + /* update maildir data */ + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = maildirdriver_maildir_error_to_mail_error(r); + goto err; + } + + msg_filename = maildir_message_get(md, uid); + if (msg_filename == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + r = stat(msg_filename, &stat_info); + free(msg_filename); + if (r < 0) { + res = MAIL_ERROR_INVAL; + goto err; + } + + /* create message */ + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_init(msg, session, maildir_cached_message_driver, + index, stat_info.st_size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto err; + } + + msg->msg_uid = strdup(uid); + if (msg->msg_uid == NULL) { + mailmessage_free(msg); + res = r; + goto err; + } + + * result = msg; + + return MAIL_NO_ERROR; + + close_db: + mail_cache_db_close_unlock(filename, uid_db); + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_cached.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_cached.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_cached.h,v 1.4 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_CACHED_H + +#define MAILDIRDRIVER_CACHED_H + +#include <libetpan/maildriver.h> +#include <libetpan/maildirdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * maildir_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,370 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_cached_message.c,v 1.9 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "maildirdriver_message.h" + +#include "mailmessage_tools.h" +#include "maildirdriver.h" +#include "maildir.h" +#include "generic_cache.h" +#include "mail_cache_db.h" +#include "maildirdriver_tools.h" + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif +#ifdef _MSC_VER +# include "win_etpan.h" +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> + +static int get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static int prefetch(mailmessage * msg_info); + +static void prefetch_free(struct generic_message_t * msg); + +static int initialize(mailmessage * msg_info); + +static void check(mailmessage * msg_info); + +static mailmessage_driver local_maildir_cached_message_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* msg_name */ "maildir-cached", + + /* msg_initialize */ initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ check, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mailmessage_generic_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_header, + /* msg_fetch_size */ NULL, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ get_flags, +#else + .msg_name = "maildir-cached", + + .msg_initialize = initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = check, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mailmessage_generic_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_header, + .msg_fetch_size = NULL, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = get_flags, +#endif +}; + +mailmessage_driver * maildir_cached_message_driver = +&local_maildir_cached_message_driver; + +struct maildir_msg_data { + int fd; +}; + +#if 0 +static inline struct maildir_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->session->data; +} + +static inline mailsession * cached_session_get_ancestor(mailsession * session) +{ + return get_data(session)->session; +} + +static inline struct maildir_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->data; +} + +static struct maildir * get_maildir_session(mailmessage * msg) +{ + return cached_session_get_ancestor_data(msg->session)->session; +} +#endif +static inline struct maildir_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline struct maildir_cached_session_state_data * +cached_session_get_data(mailsession * s) +{ + return s->sess_data; +} + +static inline mailsession * cached_session_get_ancestor(mailsession * s) +{ + return cached_session_get_data(s)->md_ancestor; +} + +static inline struct maildir_session_state_data * +cached_session_get_ancestor_data(mailsession * s) +{ + return cached_session_get_ancestor(s)->sess_data; +} + +static inline struct maildir_session_state_data * +get_session_ancestor_data(mailmessage * msg) +{ + return cached_session_get_ancestor_data(msg->msg_session); +} + +static inline struct maildir * +cached_session_get_maildir_session(mailsession * session) +{ + return cached_session_get_ancestor_data(session)->md_session; +} + +static inline struct maildir * get_maildir_session(mailmessage * msg) +{ + return cached_session_get_maildir_session(msg->msg_session); +} + +static int prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int res; + struct maildir_msg_data * data; + char * filename; + int fd; + char * mapping; + struct maildir * md; + + md = get_maildir_session(msg_info); + + filename = maildir_message_get(md, msg_info->msg_uid); + if (filename == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fd = open(filename, O_RDONLY); + free(filename); + if (fd == -1) { + res = MAIL_ERROR_FILE; + goto err; + } + + mapping = mmap(NULL, msg_info->msg_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == (char *)MAP_FAILED) { + res = MAIL_ERROR_FILE; + goto close; + } + + data = malloc(sizeof(* data)); + if (data == NULL) { + res = MAIL_ERROR_MEMORY; + goto unmap; + } + + data->fd = fd; + + msg = msg_info->msg_data; + + msg->msg_data = data; + msg->msg_message = mapping; + msg->msg_length = msg_info->msg_size; + + return MAIL_NO_ERROR; + + unmap: + munmap(mapping, msg_info->msg_size); + close: + close(fd); + err: + return res; +} + +static void prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + struct maildir_msg_data * data; + + munmap(msg->msg_message, msg->msg_length); + msg->msg_message = NULL; + data = msg->msg_data; + close(data->fd); + free(data); + } +} + +static int initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + msg->msg_prefetch = prefetch; + msg->msg_prefetch_free = prefetch_free; + + return MAIL_NO_ERROR; +} + +static void check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_session_ancestor_data(msg_info)->md_flags_store, msg_info); + + r = mail_flags_store_set(get_cached_session_data(msg_info)->md_flags_store, msg_info); + /* ignore errors */ + } +} + +#define FLAGS_NAME "flags.db" + +static int get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + struct mail_cache_db * cache_db_flags; + chashdatum key; + chashdatum value; + struct maildir * md; + struct mail_flags * flags; + struct maildir_cached_session_state_data * data; + struct maildir_msg * md_msg; + int r; + uint32_t driver_flags; + char filename_flags[PATH_MAX]; + char keyname[PATH_MAX]; + MMAPString * mmapstr; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + data = get_cached_session_data(msg_info); + flags = mail_flags_store_get(data->md_flags_store, + msg_info->msg_index); + if (flags != NULL) { + msg_info->msg_flags = flags; + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->md_flags_directory, MAIL_DIR_SEPARATOR, data->md_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) + return MAIL_ERROR_FILE; + + snprintf(keyname, PATH_MAX, "%s-flags", msg_info->msg_uid); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + return MAIL_ERROR_MEMORY; + } + + r = generic_cache_flags_read(cache_db_flags, mmapstr, keyname, &flags); + mmap_string_free(mmapstr); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + if (r != MAIL_NO_ERROR) { + flags = mail_flags_new_empty(); + if (flags == NULL) + return MAIL_ERROR_MEMORY; + } + + md = get_maildir_session(msg_info); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + key.data = msg_info->msg_uid; + key.len = strlen(msg_info->msg_uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + return MAIL_ERROR_MSG_NOT_FOUND; + + md_msg = value.data; + + driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags); + + flags->fl_flags = driver_flags; + msg_info->msg_flags = flags; + + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_cached_message.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_cached_message.h,v 1.3 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_CACHED_MESSAGE_H + +#define MAILDIRDRIVER_CACHED_MESSAGE_H + +#include <libetpan/maildirdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * maildir_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_message.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_message.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,292 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_message.c,v 1.9 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "maildirdriver_message.h" + +#include "maildirdriver_tools.h" + +#include "mailmessage_tools.h" +#include "maildirdriver.h" +#include "maildir.h" +#include "generic_cache.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> +#ifdef _MSC_VER +# include "win_etpan.h" +#endif + +static int get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static int prefetch(mailmessage * msg_info); + +static void prefetch_free(struct generic_message_t * msg); + +static int initialize(mailmessage * msg_info); + +static void check(mailmessage * msg_info); + +static mailmessage_driver local_maildir_message_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* msg_name */ "maildir", + + /* msg_initialize */ initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ check, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mailmessage_generic_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_header, + /* msg_fetch_size */ NULL, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ get_flags +#else + .msg_name = "maildir", + + .msg_initialize = initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = check, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mailmessage_generic_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_header, + .msg_fetch_size = NULL, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = get_flags, +#endif +}; + +mailmessage_driver * maildir_message_driver = &local_maildir_message_driver; + +struct maildir_msg_data { + int fd; +}; + +static inline struct maildir_session_state_data * +get_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static struct maildir * get_maildir_session(mailmessage * msg) +{ + return get_session_data(msg)->md_session; +} + +static int prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int res; + struct maildir_msg_data * data; + char * filename; + int fd; + char * mapping; + struct maildir * md; + + md = get_maildir_session(msg_info); + + if (msg_info->msg_uid == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + filename = maildir_message_get(md, msg_info->msg_uid); + if (filename == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + fd = open(filename, O_RDONLY); + free(filename); + if (fd == -1) { + res = MAIL_ERROR_FILE; + goto err; + } + + mapping = mmap(NULL, msg_info->msg_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == (char *)MAP_FAILED) { + res = MAIL_ERROR_FILE; + goto close; + } + + data = malloc(sizeof(* data)); + if (data == NULL) { + res = MAIL_ERROR_MEMORY; + goto unmap; + } + + data->fd = fd; + + msg = msg_info->msg_data; + + msg->msg_data = data; + msg->msg_message = mapping; + msg->msg_length = msg_info->msg_size; + + return MAIL_NO_ERROR; + + unmap: + munmap(mapping, msg_info->msg_size); + close: + close(fd); + err: + return res; +} + +static void prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + struct maildir_msg_data * data; + + munmap(msg->msg_message, msg->msg_length); + msg->msg_message = NULL; + data = msg->msg_data; + close(data->fd); + free(data); + } +} + +static int initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + msg->msg_prefetch = prefetch; + msg->msg_prefetch_free = prefetch_free; + + return MAIL_NO_ERROR; +} + +static void check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_session_data(msg_info)->md_flags_store, + msg_info); + /* ignore errors */ + } +} + +static int get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + chashdatum key; + chashdatum value; + struct maildir * md; + struct mail_flags * flags; + struct maildir_session_state_data * data; + struct maildir_msg * md_msg; + int r; + uint32_t driver_flags; + clist * ext; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + data = get_session_data(msg_info); + flags = mail_flags_store_get(data->md_flags_store, + msg_info->msg_index); + if (flags != NULL) { + msg_info->msg_flags = flags; + * result = msg_info->msg_flags; + return MAIL_NO_ERROR; + } + + md = get_maildir_session(msg_info); + if (md == NULL) + return MAIL_ERROR_BAD_STATE; + + key.data = msg_info->msg_uid; + key.len = strlen(msg_info->msg_uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + return MAIL_ERROR_MSG_NOT_FOUND; + + md_msg = value.data; + + driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags); + + ext = clist_new(); + if (ext == NULL) + return MAIL_ERROR_MEMORY; + + msg_info->msg_flags = mail_flags_new(driver_flags, ext); + + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_message.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_message.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_message.h,v 1.3 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_MESSAGE_H + +#define MAILDIRDRIVER_MESSAGE_H + +#include <libetpan/maildirdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * maildir_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_tools.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_tools.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,202 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_tools.c,v 1.7 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmessage.h" +#include "maildirdriver_tools.h" +#include "maildir.h" +#include "generic_cache.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <string.h> + +int maildirdriver_maildir_error_to_mail_error(int error) +{ + switch (error) { + case MAILDIR_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILDIR_ERROR_CREATE: + return MAIL_ERROR_FILE; + + case MAILDIR_ERROR_DIRECTORY: + return MAIL_ERROR_FILE; + + case MAILDIR_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILDIR_ERROR_FILE: + return MAIL_ERROR_FILE; + + case MAILDIR_ERROR_FOLDER: + return MAIL_ERROR_FOLDER; + + case MAILDIR_ERROR_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + default: + return MAIL_ERROR_INVAL; + } +} + + + +uint32_t maildirdriver_maildir_flags_to_flags(uint32_t md_flags) +{ + uint32_t flags; + + flags = 0; + if ((md_flags & MAILDIR_FLAG_NEW) != 0) + flags |= MAIL_FLAG_NEW; + + if ((md_flags & MAILDIR_FLAG_SEEN) != 0) + flags |= MAIL_FLAG_SEEN; + + if ((md_flags & MAILDIR_FLAG_REPLIED) != 0) + flags |= MAIL_FLAG_ANSWERED; + + if ((md_flags & MAILDIR_FLAG_FLAGGED) != 0) + flags |= MAIL_FLAG_FLAGGED; + + if ((md_flags & MAILDIR_FLAG_TRASHED) != 0) + flags |= MAIL_FLAG_DELETED; + + return flags; +} + +uint32_t maildirdriver_flags_to_maildir_flags(uint32_t flags) +{ + uint32_t md_flags; + + md_flags = 0; + if ((flags & MAIL_FLAG_NEW) != 0) + md_flags |= MAILDIR_FLAG_NEW; + + if ((flags & MAIL_FLAG_SEEN) != 0) + md_flags |= MAILDIR_FLAG_SEEN; + + if ((flags & MAIL_FLAG_ANSWERED) != 0) + md_flags |= MAILDIR_FLAG_REPLIED; + + if ((flags & MAIL_FLAG_FLAGGED) != 0) + md_flags |= MAILDIR_FLAG_FLAGGED; + + if ((flags & MAIL_FLAG_DELETED) != 0) + md_flags |= MAILDIR_FLAG_TRASHED; + + return md_flags; +} + + +int maildir_get_messages_list(mailsession * session, struct maildir * md, + mailmessage_driver * message_driver, + struct mailmessage_list ** result) +{ + unsigned int i; + struct mailmessage_list * env_list; + int r; + carray * tab; + int res; + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(md->mdir_msg_list) ; i++) { + struct maildir_msg * md_msg; + mailmessage * msg; + char * filename; + struct stat stat_info; + + md_msg = carray_get(md->mdir_msg_list, i); + + filename = maildir_message_get(md, md_msg->msg_uid); + r = stat(filename, &stat_info); + free(filename); + if (r < 0) + continue; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, message_driver, + i + 1, stat_info.st_size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto free_list; + } + + msg->msg_uid = strdup(md_msg->msg_uid); + if (msg->msg_uid == NULL) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(tab) ; i ++) + mailmessage_free(carray_get(tab, i)); + carray_free(tab); + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_tools.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_tools.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_tools.h,v 1.3 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_TOOLS_H + +#define MAILDIRDRIVER_TOOLS_H + +#include "maildriver_types.h" +#include "maildir.h" + +int maildirdriver_maildir_error_to_mail_error(int error); + +uint32_t maildirdriver_maildir_flags_to_flags(uint32_t md_flags); + +uint32_t maildirdriver_flags_to_maildir_flags(uint32_t flags); + +int maildir_get_messages_list(mailsession * session, struct maildir * md, + mailmessage_driver * message_driver, + struct mailmessage_list ** result); + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirdriver_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,96 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirdriver_types.h,v 1.6 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MAILDIRDRIVER_TYPES_H + +#define MAILDIRDRIVER_TYPES_H + +#include <libetpan/libetpan-config.h> + +#include <libetpan/maildriver_types.h> +#include <libetpan/maildir.h> +#include <libetpan/generic_cache_types.h> +#include <libetpan/mailstorage_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct maildir_session_state_data { + struct maildir * md_session; + struct mail_flags_store * md_flags_store; +}; + +enum { + MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY = 1, + MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY +}; + +struct maildir_cached_session_state_data { + mailsession * md_ancestor; + char * md_quoted_mb; + struct mail_flags_store * md_flags_store; + char md_cache_directory[PATH_MAX]; + char md_flags_directory[PATH_MAX]; +}; + +/* maildir storage */ + +/* + maildir_mailstorage is the state data specific to the maildir storage. + + - pathname is the path of the maildir storage. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct maildir_mailstorage { + char * md_pathname; + + int md_cached; + char * md_cache_directory; + char * md_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirstorage.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirstorage.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,205 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirstorage.c,v 1.10 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "maildirstorage.h" +#include "mailstorage.h" + +#include "mail.h" +#include "mailmessage.h" +#include "maildirdriver.h" +#include "maildirdriver_cached.h" +#include "maildriver.h" + +#include <stdlib.h> +#include <string.h> + +/* maildir storage */ + +static int maildir_mailstorage_connect(struct mailstorage * storage); +static int +maildir_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void maildir_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver maildir_mailstorage_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sto_name */ "maildir", + /* sto_connect */ maildir_mailstorage_connect, + /* sto_get_folder_session */ maildir_mailstorage_get_folder_session, + /* sto_uninitialize */ maildir_mailstorage_uninitialize, +#else + .sto_name = "maildir", + .sto_connect = maildir_mailstorage_connect, + .sto_get_folder_session = maildir_mailstorage_get_folder_session, + .sto_uninitialize = maildir_mailstorage_uninitialize, +#endif +}; + +LIBETPAN_EXPORT +int maildir_mailstorage_init(struct mailstorage * storage, + const char * md_pathname, int md_cached, + const char * md_cache_directory, const char * md_flags_directory) +{ + struct maildir_mailstorage * maildir_storage; + + maildir_storage = malloc(sizeof(* maildir_storage)); + if (maildir_storage == NULL) + goto err; + + maildir_storage->md_pathname = strdup(md_pathname); + if (maildir_storage->md_pathname == NULL) + goto free; + + maildir_storage->md_cached = md_cached; + + if (md_cached && (md_cache_directory != NULL) && + (md_flags_directory != NULL)) { + maildir_storage->md_cache_directory = strdup(md_cache_directory); + if (maildir_storage->md_cache_directory == NULL) + goto free_pathname; + + maildir_storage->md_flags_directory = strdup(md_flags_directory); + if (maildir_storage->md_flags_directory == NULL) + goto free_cache_directory; + } + else { + maildir_storage->md_cached = FALSE; + maildir_storage->md_cache_directory = NULL; + maildir_storage->md_flags_directory = NULL; + } + + storage->sto_data = maildir_storage; + storage->sto_driver = &maildir_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(maildir_storage->md_cache_directory); + free_pathname: + free(maildir_storage->md_pathname); + free: + free(maildir_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void maildir_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct maildir_mailstorage * maildir_storage; + + maildir_storage = storage->sto_data; + if (maildir_storage->md_flags_directory != NULL) + free(maildir_storage->md_flags_directory); + if (maildir_storage->md_cache_directory != NULL) + free(maildir_storage->md_cache_directory); + free(maildir_storage->md_pathname); + free(maildir_storage); + + storage->sto_data = NULL; +} + +static int maildir_mailstorage_connect(struct mailstorage * storage) +{ + struct maildir_mailstorage * maildir_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + maildir_storage = storage->sto_data; + + if (maildir_storage->md_cached) + driver = maildir_cached_session_driver; + else + driver = maildir_session_driver; + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (maildir_storage->md_cached) { + r = mailsession_parameters(session, + MAILDIRDRIVER_CACHED_SET_CACHE_DIRECTORY, + maildir_storage->md_cache_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + r = mailsession_parameters(session, + MAILDIRDRIVER_CACHED_SET_FLAGS_DIRECTORY, + maildir_storage->md_flags_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } + + r = mailsession_connect_path(session, maildir_storage->md_pathname); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int +maildir_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} + Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirstorage.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/maildir/maildirstorage.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,70 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildirstorage.h,v 1.7 2006/06/02 15:44:29 smarinier Exp $ + */ + +#ifndef MAILDIRSTORAGE_H + +#define MAILDIRSTORAGE_H + +#include <libetpan/maildirdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + maildir_mailstorage_init is the constructor for a maildir storage. + + @param storage this is the storage to initialize. + + @param pathname is the directory that contains the mailbox. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +LIBETPAN_EXPORT +int maildir_mailstorage_init(struct mailstorage * storage, + const char * md_pathname, int md_cached, + const char * md_cache_directory, const char * md_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,30 @@ +top_builddir = ../../../.. + +HEADERS = \ + mboxdriver.h \ + mboxdriver_cached.h \ + mboxdriver_cached_message.h \ + mboxdriver_message.h \ + mboxdriver_types.h \ + mboxstorage.h + + +SOURCES = \ + mboxdriver.c \ + mboxdriver_cached.c \ + mboxdriver_cached_message.c \ + mboxdriver_message.c \ + mboxdriver_tools.c \ + mboxstorage.c + + +TARGET = libmbox +INCLUDES = -I../../interface \ + -I../../tools \ + -I$(srcdir)/low-level/mbox \ + -I$(srcdir)/low-level/mime \ + -I$(srcdir)/low-level/imf \ + -I$(srcdir)/data-types + + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,575 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver.c,v 1.43 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mboxdriver.h" + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#ifndef _MSC_VER +# include <dirent.h> +# include <unistd.h> +#endif +#include <sys/stat.h> +#include <ctype.h> +#include <stdlib.h> +#ifndef _MSC_VER +#include <sys/times.h> +#endif + +#include "mail.h" +#include "maildriver_tools.h" +#include "mailmbox.h" +#include "mboxdriver_tools.h" +#include "maildriver.h" +#include "carray.h" +#include "mboxdriver_message.h" +#include "mailmessage.h" + +static int mboxdriver_initialize(mailsession * session); + +static void mboxdriver_uninitialize(mailsession * session); + +static int mboxdriver_parameters(mailsession * session, + int id, void * value); + +static int mboxdriver_connect_path(mailsession * session, const char * path); + +static int mboxdriver_logout(mailsession * session); + +static int mboxdriver_expunge_folder(mailsession * session); + +static int mboxdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int mboxdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int mboxdriver_append_message(mailsession * session, + const char * message, size_t size); + +static int mboxdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +static int mboxdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +mboxdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int mboxdriver_remove_message(mailsession * session, uint32_t num); + +static int mboxdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int mboxdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_mbox_session_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sess_name */ "mbox", + + /* sess_initialize */ mboxdriver_initialize, + /* sess_uninitialize */ mboxdriver_uninitialize, + + /* sess_parameters */ mboxdriver_parameters, + + /* sess_connect_stream */ NULL, + + /* sess_connect_path */ mboxdriver_connect_path, + /* sess_starttls */ NULL, + /* sess_login */ NULL, + /* sess_logout */ mboxdriver_logout, + /* sess_noop */ NULL, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ NULL, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ NULL, + /* sess_expunge_folder */ mboxdriver_expunge_folder, + /* sess_status_folder */ mboxdriver_status_folder, + /* sess_messages_number */ mboxdriver_messages_number, + /* sess_recent_number */ mboxdriver_messages_number, + /* sess_unseen_number */ mboxdriver_messages_number, + /* sess_list_folders */ NULL, + /* sess_lsub_folders */ NULL, + /* sess_subscribe_folder */ NULL, + /* sess_unsubscribe_folder */ NULL, + + /* sess_append_message */ mboxdriver_append_message, + /* sess_append_message_flags */ mboxdriver_append_message_flags, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ mboxdriver_get_message, + /* sess_get_message_by_uid */ mboxdriver_get_message_by_uid, + + /* sess_get_messages_list */ mboxdriver_get_messages_list, + /* sess_get_envelopes_list */ mboxdriver_get_envelopes_list, + /* sess_remove_message */ mboxdriver_remove_message, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL, + +#else + .sess_name = "mbox", + + .sess_initialize = mboxdriver_initialize, + .sess_uninitialize = mboxdriver_uninitialize, + + .sess_parameters = mboxdriver_parameters, + + .sess_connect_path = mboxdriver_connect_path, + .sess_connect_stream = NULL, + .sess_starttls = NULL, + .sess_login = NULL, + .sess_logout = mboxdriver_logout, + .sess_noop = NULL, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = NULL, + .sess_examine_folder = NULL, + .sess_select_folder = NULL, + .sess_expunge_folder = mboxdriver_expunge_folder, + .sess_status_folder = mboxdriver_status_folder, + .sess_messages_number = mboxdriver_messages_number, + .sess_recent_number = mboxdriver_messages_number, + .sess_unseen_number = mboxdriver_messages_number, + .sess_list_folders = NULL, + .sess_lsub_folders = NULL, + .sess_subscribe_folder = NULL, + .sess_unsubscribe_folder = NULL, + + .sess_append_message = mboxdriver_append_message, + .sess_append_message_flags = mboxdriver_append_message_flags, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = mboxdriver_get_messages_list, + .sess_get_envelopes_list = mboxdriver_get_envelopes_list, + .sess_remove_message = mboxdriver_remove_message, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = mboxdriver_get_message, + .sess_get_message_by_uid = mboxdriver_get_message_by_uid, + .sess_login_sasl = NULL, +#endif +}; + +mailsession_driver * mbox_session_driver = &local_mbox_session_driver; + +static inline struct mbox_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct mailmbox_folder * get_mbox_session(mailsession * session) +{ + return get_data(session)->mbox_folder; +} + +static int mboxdriver_initialize(mailsession * session) +{ + struct mbox_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->mbox_folder = NULL; + + data->mbox_force_read_only = FALSE; + data->mbox_force_no_uid = TRUE; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + err: + return MAIL_ERROR_MEMORY; +} + +static void free_state(struct mbox_session_state_data * mbox_data) +{ + if (mbox_data->mbox_folder != NULL) { + mailmbox_done(mbox_data->mbox_folder); + mbox_data->mbox_folder = NULL; + } +} + +static void mboxdriver_uninitialize(mailsession * session) +{ + struct mbox_session_state_data * data; + + data = get_data(session); + + free_state(data); + + free(data); +} + +static int mboxdriver_parameters(mailsession * session, + int id, void * value) +{ + struct mbox_session_state_data * data; + + data = get_data(session); + + switch (id) { + case MBOXDRIVER_SET_READ_ONLY: + { + int * param; + + param = value; + + data->mbox_force_read_only = * param; + return MAIL_NO_ERROR; + } + + case MBOXDRIVER_SET_NO_UID: + { + int * param; + + param = value; + + data->mbox_force_no_uid = * param; + return MAIL_NO_ERROR; + } + } + + return MAIL_ERROR_INVAL; +} + + +static int mboxdriver_connect_path(mailsession * session, const char * path) +{ + struct mbox_session_state_data * mbox_data; + struct mailmbox_folder * folder; + int r; + + mbox_data = get_data(session); + + if (mbox_data->mbox_folder != NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_init(path, + mbox_data->mbox_force_read_only, + mbox_data->mbox_force_no_uid, + 0, + &folder); + + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + mbox_data->mbox_folder = folder; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_logout(mailsession * session) +{ + struct mbox_session_state_data * mbox_data; + + mbox_data = get_data(session); + + if (mbox_data->mbox_folder == NULL) + return MAIL_ERROR_BAD_STATE; + + free_state(mbox_data); + + mbox_data->mbox_folder = NULL; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_expunge_folder(mailsession * session) +{ + int r; + struct mbox_session_state_data * mbox_data; + + mbox_data = get_data(session); + + if (mbox_data->mbox_folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_expunge(mbox_data->mbox_folder); + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + return MAIL_NO_ERROR; +} + +static int mboxdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + uint32_t count; + int r; + + r = mboxdriver_messages_number(session, mb, &count); + if (r != MAIL_NO_ERROR) + return r; + + * result_messages = count; + * result_recent = count; + * result_unseen = count; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + struct mailmbox_folder * folder; + int r; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_STATUS; + + r = mailmbox_validate_read_lock(folder); + if (r != MAIL_NO_ERROR) + return r; + + mailmbox_read_unlock(folder); + + * result = carray_count(folder->mb_tab) - folder->mb_deleted_count; + + return MAILMBOX_NO_ERROR; +} + +/* messages operations */ + +static int mboxdriver_append_message(mailsession * session, + const char * message, size_t size) +{ + int r; + struct mailmbox_folder * folder; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_APPEND; + + r = mailmbox_append_message(folder, message, size); + + switch (r) { + case MAILMBOX_ERROR_FILE: + return MAIL_ERROR_DISKSPACE; + default: + return mboxdriver_mbox_error_to_mail_error(r); + } +} + +static int mboxdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + return mboxdriver_append_message(session, message, size); +} + +static int mboxdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct mailmbox_folder * folder; + int res; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + return mbox_get_messages_list(folder, session, mbox_message_driver, result); + + err: + return res; +} + +static int +mboxdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + struct mailmbox_folder * folder; + unsigned int i; + int r; + int res; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + char * headers; + size_t headers_len; + size_t cur_token; + + msg = carray_get(env_list->msg_tab, i); + if (msg == NULL) + continue; + + if (msg->msg_fields != NULL) + continue; + + r = mailmbox_fetch_msg_headers_no_lock(folder, + msg->msg_index, &headers, &headers_len); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto unlock; + } + + cur_token = 0; + r = mailimf_envelope_fields_parse(headers, headers_len, + &cur_token, &fields); + + if (r != MAILIMF_NO_ERROR) + continue; + + msg->msg_fields = fields; + } + + mailmbox_read_unlock(folder); + + return MAIL_NO_ERROR; + + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + + +static int mboxdriver_remove_message(mailsession * session, uint32_t num) +{ + int r; + struct mailmbox_folder * folder; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_DELETE; + + r = mailmbox_delete_msg(folder, num); + + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int mboxdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, mbox_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t num; + char * p; + chashdatum key; + chashdatum data; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int r; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = strtoul(uid, &p, 10); + if (p == uid || * p != '-') + return MAIL_ERROR_INVAL; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r == 0) { + char * body_len_p = p + 1; + size_t body_len; + + info = data.data; + /* Check if the cached message has the same UID */ + body_len = strtoul(body_len_p, &p, 10); + if (p == body_len_p || * p != '\0') + return MAIL_ERROR_INVAL; + + if (body_len == info->msg_body_len) + return mboxdriver_get_message(session, num, result); + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver.h,v 1.14 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MBOXDRIVER_H + +#define MBOXDRIVER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mboxdriver_types.h> + +extern mailsession_driver * mbox_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_cached.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_cached.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1397 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_cached.c,v 1.53 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mboxdriver_cached.h" + +#include <stdio.h> +#include <string.h> +#ifdef _MSC_VER +# include "win_etpan.h" +#else +# include <dirent.h> +# include <unistd.h> +#endif +#include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> + +#include "mail.h" +#include "mail_cache_db.h" +#include "mboxdriver.h" +#include "mboxdriver_tools.h" +#include "maildriver_tools.h" +#include "mailmbox.h" +#include "maildriver.h" +#include "carray.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mboxdriver_cached_message.h" +#include "libetpan-config.h" + +static int mboxdriver_cached_initialize(mailsession * session); + +static void mboxdriver_cached_uninitialize(mailsession * session); + +static int mboxdriver_cached_parameters(mailsession * session, + int id, void * value); + +static int mboxdriver_cached_connect_path(mailsession * session, const char * path); + +static int mboxdriver_cached_logout(mailsession * session); + +static int mboxdriver_cached_check_folder(mailsession * session); + +static int mboxdriver_cached_expunge_folder(mailsession * session); + +static int mboxdriver_cached_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); +static int mboxdriver_cached_messages_number(mailsession * session, const char * mb, + uint32_t * result); +static int mboxdriver_cached_recent_number(mailsession * session, const char * mb, + uint32_t * result); +static int mboxdriver_cached_unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +static int mboxdriver_cached_append_message(mailsession * session, + const char * message, size_t size); + +static int mboxdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +static int +mboxdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +mboxdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int mboxdriver_cached_remove_message(mailsession * session, + uint32_t num); + +static int mboxdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int mboxdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_mbox_cached_session_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sess_name */ "mbox-cached", + + /* sess_initialize */ mboxdriver_cached_initialize, + /* sess_uninitialize */ mboxdriver_cached_uninitialize, + + /* sess_parameters */ mboxdriver_cached_parameters, + + /* sess_connect_stream */ NULL, + /* sess_connect_path */ mboxdriver_cached_connect_path, + /* sess_starttls */ NULL, + /* sess_login */ NULL, + /* sess_logout */ mboxdriver_cached_logout, + /* sess_noop */ NULL, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ mboxdriver_cached_check_folder, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ NULL, + /* sess_expunge_folder */ mboxdriver_cached_expunge_folder, + /* sess_status_folder */ mboxdriver_cached_status_folder, + /* sess_messages_number */ mboxdriver_cached_messages_number, + /* sess_recent_number */ mboxdriver_cached_recent_number, + /* sess_unseen_number */ mboxdriver_cached_unseen_number, + /* sess_list_folders */ NULL, + /* sess_lsub_folders */ NULL, + /* sess_subscribe_folder */ NULL, + /* sess_unsubscribe_folder */ NULL, + + /* sess_append_message */ mboxdriver_cached_append_message, + /* sess_append_message_flags */ mboxdriver_cached_append_message_flags, + + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ mboxdriver_cached_get_message, + /* sess_get_message_by_uid */ mboxdriver_cached_get_message_by_uid, + + /* sess_get_messages_list */ mboxdriver_cached_get_messages_list, + /* sess_get_envelopes_list */ mboxdriver_cached_get_envelopes_list, + /* sess_remove_message */ mboxdriver_cached_remove_message, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL, + +#else + .sess_name = "mbox-cached", + + .sess_initialize = mboxdriver_cached_initialize, + .sess_uninitialize = mboxdriver_cached_uninitialize, + + .sess_parameters = mboxdriver_cached_parameters, + + .sess_connect_path = mboxdriver_cached_connect_path, + .sess_connect_stream = NULL, + .sess_starttls = NULL, + .sess_login = NULL, + .sess_logout = mboxdriver_cached_logout, + .sess_noop = NULL, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = mboxdriver_cached_check_folder, + .sess_examine_folder = NULL, + .sess_select_folder = NULL, + .sess_expunge_folder = mboxdriver_cached_expunge_folder, + .sess_status_folder = mboxdriver_cached_status_folder, + .sess_messages_number = mboxdriver_cached_messages_number, + .sess_recent_number = mboxdriver_cached_recent_number, + .sess_unseen_number = mboxdriver_cached_unseen_number, + .sess_list_folders = NULL, + .sess_lsub_folders = NULL, + .sess_subscribe_folder = NULL, + .sess_unsubscribe_folder = NULL, + + .sess_append_message = mboxdriver_cached_append_message, + .sess_append_message_flags = mboxdriver_cached_append_message_flags, + + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = mboxdriver_cached_get_messages_list, + .sess_get_envelopes_list = mboxdriver_cached_get_envelopes_list, + .sess_remove_message = mboxdriver_cached_remove_message, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = mboxdriver_cached_get_message, + .sess_get_message_by_uid = mboxdriver_cached_get_message_by_uid, + .sess_login_sasl = NULL, +#endif +}; + +mailsession_driver * mbox_cached_session_driver = +&local_mbox_cached_session_driver; + + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + + + +static int mbox_error_to_mail_error(int error) +{ + switch (error) { + case MAILMBOX_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILMBOX_ERROR_PARSE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_INVAL: + return MAIL_ERROR_INVAL; + + case MAILMBOX_ERROR_FILE_NOT_FOUND: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILMBOX_ERROR_TEMPORARY_FILE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_FILE: + return MAIL_ERROR_FILE; + + case MAILMBOX_ERROR_MSG_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + case MAILMBOX_ERROR_READONLY: + return MAIL_ERROR_READONLY; + + default: + return MAIL_ERROR_INVAL; + } +} + + + + +static inline struct mbox_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->mbox_ancestor; +} + +static inline struct mbox_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + +static inline struct mailmbox_folder * +get_mbox_session(mailsession * session) +{ + return get_ancestor_data(session)->mbox_folder; +} + +static int mboxdriver_cached_initialize(mailsession * session) +{ + struct mbox_cached_session_state_data * cached_data; + struct mbox_session_state_data * mbox_data; + + cached_data = malloc(sizeof(* cached_data)); + if (cached_data == NULL) + goto err; + + cached_data->mbox_flags_store = mail_flags_store_new(); + if (cached_data->mbox_flags_store == NULL) + goto free; + + cached_data->mbox_ancestor = mailsession_new(mbox_session_driver); + if (cached_data->mbox_ancestor == NULL) + goto free_store; + + cached_data->mbox_quoted_mb = NULL; + /* + UID must be enabled to take advantage of the cache + */ + mbox_data = cached_data->mbox_ancestor->sess_data; + mbox_data->mbox_force_no_uid = FALSE; + + session->sess_data = cached_data; + + return MAIL_NO_ERROR; + + free_store: + mail_flags_store_free(cached_data->mbox_flags_store); + free: + free(cached_data); + err: + return MAIL_ERROR_MEMORY; +} + +static void free_state(struct mbox_cached_session_state_data * mbox_data) +{ + if (mbox_data->mbox_quoted_mb) { + free(mbox_data->mbox_quoted_mb); + mbox_data->mbox_quoted_mb = NULL; + } +} + +static int mbox_flags_store_process(char * flags_directory, char * quoted_mb, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + if (quoted_mb == NULL) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + flags_directory, MAIL_DIR_SEPARATOR, quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + if (r != MAIL_NO_ERROR) { + /* ignore errors */ + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void mboxdriver_cached_uninitialize(mailsession * session) +{ + struct mbox_cached_session_state_data * data; + + data = get_cached_data(session); + + mbox_flags_store_process(data->mbox_flags_directory, + data->mbox_quoted_mb, + data->mbox_flags_store); + + mail_flags_store_free(data->mbox_flags_store); + + free_state(data); + mailsession_free(data->mbox_ancestor); + free(data); + + session->sess_data = NULL; +} + +static int mboxdriver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct mbox_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + switch (id) { + case MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(data->mbox_cache_directory, value, PATH_MAX); + data->mbox_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->mbox_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(data->mbox_flags_directory, value, PATH_MAX); + data->mbox_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->mbox_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case MBOXDRIVER_SET_NO_UID: + return MAIL_ERROR_INVAL; + + default: + return mailsession_parameters(data->mbox_ancestor, id, value); + } +} + + +static int get_cache_directory(mailsession * session, + const char * path, char ** result) +{ + char * quoted_mb; + char dirname[PATH_MAX]; + int res; + int r; + struct mbox_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + quoted_mb = maildriver_quote_mailbox(path); + if (quoted_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(dirname, PATH_MAX, "%s%c%s", + cached_data->mbox_cache_directory, MAIL_DIR_SEPARATOR, quoted_mb); + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + snprintf(dirname, PATH_MAX, "%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, quoted_mb); + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + * result = quoted_mb; + + return MAIL_NO_ERROR; + + free: + free(quoted_mb); + err: + return res; +} + + + + +#define FILENAME_MAX_UID "max-uid" + +/* write max uid current value */ + +static int write_max_uid_value(mailsession * session) +{ + int r; + char filename[PATH_MAX]; + FILE * f; + int res; + +#if 0 + struct mbox_session_state_data * mbox_data; +#endif + struct mbox_cached_session_state_data * cached_data; + int fd; + + MMAPString * mmapstr; + size_t cur_token; + struct mailmbox_folder * folder; + + /* expunge the mailbox */ + +#if 0 + mbox_data = get_ancestor(session)->data; +#endif + folder = get_mbox_session(session); + + r = mailmbox_validate_write_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mbox_error_to_mail_error(r); + goto err; + } + + r = mailmbox_expunge_no_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + cached_data = get_cached_data(session); + + snprintf(filename, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, MAIL_DIR_SEPARATOR, FILENAME_MAX_UID); + + fd = creat(filename, S_IRUSR | S_IWUSR); + if (fd < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + f = fdopen(fd, "w"); + if (f == NULL) { + close(fd); + res = MAIL_ERROR_FILE; + goto unlock; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close; + } + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mailimf_cache_int_write(mmapstr, &cur_token, + folder->mb_written_uid); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + fwrite(mmapstr->str, 1, mmapstr->len, f); + + mmap_string_free(mmapstr); + fclose(f); + mailmbox_write_unlock(folder); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close: + fclose(f); + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + +static int read_max_uid_value(mailsession * session, uint32_t * result) +{ + int r; + char filename[PATH_MAX]; + FILE * f; + uint32_t written_uid; + int res; + + struct mbox_cached_session_state_data * cached_data; + + MMAPString * mmapstr; + size_t cur_token; + char buf[sizeof(uint32_t)]; + size_t read_size; + + cached_data = get_cached_data(session); + + snprintf(filename, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, MAIL_DIR_SEPARATOR, FILENAME_MAX_UID); + + f = fopen(filename, "r"); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + read_size = fread(buf, 1, sizeof(uint32_t), f); + + mmapstr = mmap_string_new_len(buf, read_size); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close; + } + + cur_token = 0; + + r = mailimf_cache_int_read(mmapstr, &cur_token, &written_uid); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + mmap_string_free(mmapstr); + fclose(f); + + * result = written_uid; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close: + fclose(f); + err: + return res; +} + +static int mboxdriver_cached_connect_path(mailsession * session, const char * path) +{ + int r; + int res; + char * quoted_mb; + struct mbox_cached_session_state_data * cached_data; + struct mbox_session_state_data * ancestor_data; + struct mailmbox_folder * folder; + uint32_t written_uid; + + folder = get_mbox_session(session); + if (folder != NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + quoted_mb = NULL; + r = get_cache_directory(session, path, "ed_mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + cached_data = get_cached_data(session); + free_state(cached_data); + + cached_data->mbox_quoted_mb = quoted_mb; + + written_uid = 0; + r = read_max_uid_value(session, &written_uid); + /* ignore errors */ + + ancestor_data = get_ancestor_data(session); + + r = mailmbox_init(path, + ancestor_data->mbox_force_read_only, + ancestor_data->mbox_force_no_uid, + written_uid, + &folder); + + if (r != MAILMBOX_NO_ERROR) { + cached_data->mbox_quoted_mb = NULL; + + res = mboxdriver_mbox_error_to_mail_error(r); + goto free; + } + + ancestor_data->mbox_folder = folder; + + return MAIL_NO_ERROR; + + free: + free(quoted_mb); + err: + return res; +} + + +static int mboxdriver_cached_logout(mailsession * session) +{ + struct mbox_cached_session_state_data * cached_data; + int r; + + r = write_max_uid_value(session); + + cached_data = get_cached_data(session); + + mbox_flags_store_process(cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, + cached_data->mbox_flags_store); + + r = mailsession_logout(get_ancestor(session)); + if (r != MAIL_NO_ERROR) + return r; + + free_state(cached_data); + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_check_folder(mailsession * session) +{ + struct mbox_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + mbox_flags_store_process(cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, + cached_data->mbox_flags_store); + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_expunge_folder(mailsession * session) +{ + struct mailmbox_folder * folder; + int res; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + struct mbox_cached_session_state_data * data; + int r; + unsigned int i; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + data = get_cached_data(session); + if (data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mbox_flags_store_process(data->mbox_flags_directory, + data->mbox_quoted_mb, + data->mbox_flags_store); + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * msg_info; + struct mail_flags * flags; + + msg_info = carray_get(folder->mb_tab, i); + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + session, msg_info->msg_uid, &flags); + if (r != MAIL_NO_ERROR) + continue; + + if (flags->fl_flags & MAIL_FLAG_DELETED) { + r = mailmbox_delete_msg(folder, msg_info->msg_uid); + } + + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + r = mailmbox_expunge(folder); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mboxdriver_cached_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + struct mailmbox_folder * folder; + int res; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + struct mbox_cached_session_state_data * data; + int r; + unsigned int i; + uint32_t recent; + uint32_t unseen; + uint32_t num; + + num = 0; + recent = 0; + unseen = 0; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + data = get_cached_data(session); + if (data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmbox_validate_read_lock(folder); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mailmbox_read_unlock(folder); + + mbox_flags_store_process(data->mbox_flags_directory, data->mbox_quoted_mb, + data->mbox_flags_store); + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * msg_info; + struct mail_flags * flags; + + msg_info = carray_get(folder->mb_tab, i); + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + session, msg_info->msg_uid, &flags); + if (r != MAIL_NO_ERROR) { + recent ++; + unseen ++; + num ++; + continue; + } + + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + + num ++; + + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + * result_messages = num; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mboxdriver_cached_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + return mailsession_messages_number(get_ancestor(session), mb, result); +} + + +static int mboxdriver_cached_recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = mboxdriver_cached_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = mboxdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +/* messages operations */ + +static int mboxdriver_cached_append_message(mailsession * session, + const char * message, size_t size) +{ + return mboxdriver_cached_append_message_flags(session, + message, size, NULL); +} + +static int mboxdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + int r; + struct mailmbox_folder * folder; + struct mbox_cached_session_state_data * data; + unsigned int uid; + struct mailmbox_msg_info * msg_info; + chashdatum key; + chashdatum value; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + MMAPString * mmapstr; + char keyname[PATH_MAX]; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_APPEND; + + r = mailmbox_append_message_uid(folder, message, size, &uid); + + switch (r) { + case MAILMBOX_ERROR_FILE: + return MAIL_ERROR_DISKSPACE; + case MAILMBOX_NO_ERROR: + break; + default: + return mboxdriver_mbox_error_to_mail_error(r); + } + + /* could store in flags store instead */ + + if (flags == NULL) + goto exit; + + key.data = &uid; + key.len = sizeof(uid); + r = chash_get(folder->mb_hash, &key, &value); + if (r < 0) + goto exit; + + msg_info = value.data; + + data = get_cached_data(session); + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + data->mbox_flags_directory, MAIL_DIR_SEPARATOR, data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) + goto exit; + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) + goto close_db_flags; + + snprintf(keyname, PATH_MAX, "%u-%lu", uid, + (unsigned long) msg_info->msg_body_len); + + r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr, keyname, flags); + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + if (r != MAIL_NO_ERROR) + goto exit; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + exit: + return MAIL_NO_ERROR; +} + +static int +mboxdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct mailmbox_folder * folder; + int res; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + return mbox_get_uid_messages_list(folder, + session, mbox_cached_message_driver, result); + + err: + return res; +} + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mailimf_fields * fields; + int res; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%lu-envelope", num, + (unsigned long) info->msg_body_len); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields * fields) +{ + int r; + char keyname[PATH_MAX]; + int res; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%lu-envelope", num, + (unsigned long) info->msg_body_len); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +mboxdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + struct mbox_cached_session_state_data * cached_data; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + int res; + struct mailmbox_folder * folder; + + folder = get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + cached_data = get_cached_data(session); + if (cached_data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mbox_flags_store_process(cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, + cached_data->mbox_flags_store); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename_env, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_cache_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, ENV_NAME); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s%c%s%c%s", + cached_data->mbox_flags_directory, MAIL_DIR_SEPARATOR, + cached_data->mbox_quoted_mb, + MAIL_DIR_SEPARATOR, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + struct mail_flags * flags; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, session, + msg->msg_index, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + + if (msg->msg_flags == NULL) { + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + session, msg->msg_index, + &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + /* add flags */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) + msg->msg_flags = mail_flags_new_empty(); + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close_db_env; + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + /* msg->msg_index is the numerical UID of the message */ + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = mboxdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + + +static int +mboxdriver_cached_remove_message(mailsession * session, uint32_t num) +{ + return mailsession_remove_message(get_ancestor(session), num); +} + +static int mboxdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, mbox_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int mboxdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t num; + char * p; + chashdatum key; + chashdatum data; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int r; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = strtoul(uid, &p, 10); + if (p == uid || * p != '-') + return MAIL_ERROR_INVAL; + + folder = get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r == 0) { + char * body_len_p = p + 1; + size_t body_len; + + info = data.data; + /* Check if the cached message has the same UID */ + body_len = strtoul(body_len_p, &p, 10); + if (p == body_len_p || * p != '\0') + return MAIL_ERROR_INVAL; + + if (body_len == info->msg_body_len) + return mboxdriver_cached_get_message(session, num, result); + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_cached.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_cached.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_cached.h,v 1.11 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MBOXDRIVER_CACHED_H + +#define MBOXDRIVER_CACHED_H + +#include <libetpan/libetpan-config.h> + +#include <libetpan/mboxdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mbox_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,394 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_cached_message.c,v 1.25 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mboxdriver_cached_message.h" + +#include "mailmessage_tools.h" +#include "mboxdriver_tools.h" +#include "mboxdriver_cached.h" +#include "mboxdriver.h" +#include "mailmbox.h" +#include "mail_cache_db.h" +#include "generic_cache.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> + +static int mbox_prefetch(mailmessage * msg_info); + +static void mbox_prefetch_free(struct generic_message_t * msg); + +static int mbox_initialize(mailmessage * msg_info); + +static void mbox_uninitialize(mailmessage * msg_info); + +static void mbox_flush(mailmessage * msg_info); + +static void mbox_check(mailmessage * msg_info); + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result); + +static int mbox_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static mailmessage_driver local_mbox_cached_message_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* msg_name */ "mbox-cached", + + /* msg_initialize */ mbox_initialize, + /* msg_uninitialize */ mbox_uninitialize, + + /* msg_flush */ mbox_flush, + /* msg_check */ mbox_check, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mbox_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ mbox_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ mbox_get_flags, +#else + .msg_name = "mbox-cached", + + .msg_initialize = mbox_initialize, + .msg_uninitialize = mbox_uninitialize, + + .msg_flush = mbox_flush, + .msg_check = mbox_check, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mbox_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = mbox_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = mbox_get_flags, +#endif +}; + +mailmessage_driver * mbox_cached_message_driver = +&local_mbox_cached_message_driver; + +static inline struct mbox_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailsession * get_ancestor_session(mailmessage * msg) +{ + return get_cached_session_data(msg)->mbox_ancestor; +} + +static inline struct mbox_session_state_data * +get_ancestor_session_data(mailmessage * msg) +{ + return get_ancestor_session(msg)->sess_data; +} + +static inline struct mailmbox_folder * +get_mbox_session(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->mbox_folder; +} + +static int mbox_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + r = mboxdriver_fetch_msg(get_ancestor_session(msg_info), + msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void mbox_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int mbox_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[PATH_MAX]; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int res; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(msg_info); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = (char *) &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = (struct mailmbox_msg_info *) data.data; + + snprintf(static_uid, PATH_MAX, "%u-%lu", + msg_info->msg_index, (unsigned long) info->msg_body_len); + uid = strdup(static_uid); + if (uid == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + res = r; + goto err; + } + + msg = msg_info->msg_data; + + msg->msg_prefetch = mbox_prefetch; + msg->msg_prefetch_free = mbox_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static void mbox_uninitialize(mailmessage * msg_info) +{ + mailmessage_generic_uninitialize(msg_info); +} + +#define FLAGS_NAME "flags.db" + +static void mbox_flush(mailmessage * msg_info) +{ + mailmessage_generic_flush(msg_info); +} + +static void mbox_check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_cached_session_data(msg_info)->mbox_flags_store, + msg_info); + /* ignore errors */ + } +} + + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + size_t size; + + r = mboxdriver_fetch_size(get_ancestor_session(msg_info), + msg_info->msg_index, &size); + if (r != MAIL_NO_ERROR) + return r; + + * result = size; + + return MAIL_NO_ERROR; +} + +static int mbox_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + int res; + struct mbox_cached_session_state_data * cached_data; + MMAPString * mmapstr; + struct mailmbox_folder * folder; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; + } + + flags = mail_flags_store_get(get_cached_session_data(msg_info)->mbox_flags_store, + msg_info->msg_index); + + if (flags == NULL) { + folder = get_mbox_session(msg_info); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + cached_data = get_cached_session_data(msg_info); + if (cached_data->mbox_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mbox_flags_directory, + cached_data->mbox_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + if (msg_info->msg_index > folder->mb_written_uid) { + flags = mail_flags_new_empty(); + } + else { + r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr, + msg_info->msg_session, + msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + flags = mail_flags_new_empty(); + if (flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + msg = msg_info->msg_data; + if (msg->msg_message != NULL) { + return mailmessage_generic_fetch_header(msg_info, result, result_len); + } + else { + r = mboxdriver_fetch_header(get_ancestor_session(msg_info), + msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; + } +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_cached_message.h,v 1.6 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MBOXDRIVER_CACHED_MESSAGE_H + +#define MBOXDRIVER_CACHED_MESSAGE_H + +#include <libetpan/mailmessage.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mbox_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_message.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_message.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,258 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_message.c,v 1.19 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mboxdriver_message.h" + +#include "mailmessage_tools.h" +#include "mboxdriver_tools.h" +#include "mboxdriver.h" +#include "mailmbox.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> + +static int mbox_prefetch(mailmessage * msg_info); + +static void mbox_prefetch_free(struct generic_message_t * msg); + +static int mbox_initialize(mailmessage * msg_info); + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result); + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static mailmessage_driver local_mbox_message_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* msg_name */ "mbox", + + /* msg_initialize */ mbox_initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ NULL, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mbox_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ mbox_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ NULL, +#else + .msg_name = "mbox", + + .msg_initialize = mbox_initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = NULL, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mbox_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = mbox_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = NULL, +#endif +}; + +mailmessage_driver * mbox_message_driver = &local_mbox_message_driver; + +static inline struct mbox_session_state_data * get_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline struct mailmbox_folder * get_mbox_session(mailmessage * msg) +{ + return get_data(msg)->mbox_folder; +} + + +static int mbox_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + r = mboxdriver_fetch_msg(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void mbox_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int mbox_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[PATH_MAX]; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + int res; + chashdatum key; + chashdatum data; + + folder = get_mbox_session(msg_info); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(static_uid, PATH_MAX, "%u-%lu", + msg_info->msg_index, (unsigned long) info->msg_body_len); + uid = strdup(static_uid); + if (uid == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + res = r; + goto err; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = mbox_prefetch; + msg->msg_prefetch_free = mbox_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int mbox_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + size_t size; + + r = mboxdriver_fetch_size(msg_info->msg_session, + msg_info->msg_index, &size); + if (r != MAIL_NO_ERROR) + return r; + + * result = size; + + return MAIL_NO_ERROR; +} + +static int mbox_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + msg = msg_info->msg_data; + if (msg->msg_message != NULL) { + return mailmessage_generic_fetch_header(msg_info, result, result_len); + } + else { + r = mboxdriver_fetch_header(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; + } +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_message.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_message.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_message.h,v 1.6 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MBOXDRIVER_MESSAGE_H + +#define MBOXDRIVER_MESSAGE_H + +#include <libetpan/mboxdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mbox_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,439 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_tools.c,v 1.16 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mboxdriver_tools.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#include "maildriver_types.h" +#include "mailmbox.h" +#include "mboxdriver_cached.h" +#include "mboxdriver.h" +#include "generic_cache.h" +#include "mailmessage.h" +#include "imfcache.h" +#include "mail_cache_db.h" + +static inline struct mbox_session_state_data * +session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct mailmbox_folder * +session_get_mbox_session(mailsession * session) +{ + return session_get_data(session)->mbox_folder; +} + +static inline struct mbox_cached_session_state_data * +cached_session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * +cached_session_get_ancestor(mailsession * session) +{ + return cached_session_get_data(session)->mbox_ancestor; +} + +static inline struct mbox_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return cached_session_get_ancestor(session)->sess_data; +} + +static inline struct mailmbox_folder * +cached_session_get_mbox_session(mailsession * session) +{ + return session_get_mbox_session(cached_session_get_ancestor(session)); +} + + +int mboxdriver_mbox_error_to_mail_error(int error) +{ + switch (error) { + case MAILMBOX_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILMBOX_ERROR_PARSE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_INVAL: + return MAIL_ERROR_INVAL; + + case MAILMBOX_ERROR_FILE_NOT_FOUND: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILMBOX_ERROR_TEMPORARY_FILE: + return MAIL_ERROR_PARSE; + + case MAILMBOX_ERROR_FILE: + return MAIL_ERROR_FILE; + + case MAILMBOX_ERROR_MSG_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + case MAILMBOX_ERROR_READONLY: + return MAIL_ERROR_READONLY; + + default: + return MAIL_ERROR_INVAL; + } +} + +int mboxdriver_fetch_msg(mailsession * session, uint32_t index, + char ** result, size_t * result_len) +{ + int r; + char * msg_content; + size_t msg_length; + struct mailmbox_folder * folder; + + folder = session_get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_fetch_msg(folder, index, &msg_content, &msg_length); + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; +} + + +int mboxdriver_fetch_size(mailsession * session, uint32_t index, + size_t * result) +{ + struct mailmbox_folder * folder; + int r; + char * data; + size_t len; + int res; + + folder = session_get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_FETCH; + goto err; + } + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto err; + } + + r = mailmbox_fetch_msg_no_lock(folder, index, &data, &len); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto unlock; + } + + mailmbox_read_unlock(folder); + + * result = len; + + return MAIL_NO_ERROR; + + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + +int +mboxdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + struct mailmbox_msg_info * info; + struct mailmbox_folder * folder; + chashdatum key; + chashdatum data; + + folder = cached_session_get_mbox_session(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAIL_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%lu-flags", num, + (unsigned long) info->msg_body_len); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int +mboxdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +int mboxdriver_fetch_header(mailsession * session, uint32_t index, + char ** result, size_t * result_len) +{ + int r; + char * msg_content; + size_t msg_length; + struct mailmbox_folder * folder; + + folder = session_get_mbox_session(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmbox_fetch_msg_headers(folder, index, &msg_content, &msg_length); + if (r != MAILMBOX_NO_ERROR) + return mboxdriver_mbox_error_to_mail_error(r); + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; +} + +int mbox_get_locked_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + int (* lock)(struct mailmbox_folder *), + int (* unlock)(struct mailmbox_folder *), + struct mailmessage_list ** result) +{ + struct mailmessage_list * env_list; + unsigned int i; + int r; + int res; + carray * tab; + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = lock(folder); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * msg_info; + mailmessage * msg; + + msg_info = carray_get(folder->mb_tab, i); + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlock; + } + + r = mailmessage_init(msg, session, driver, msg_info->msg_uid, + msg_info->msg_size - msg_info->msg_start_len); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlock; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto unlock; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlock; + } + + unlock(folder); + + * result = env_list; + + return MAIL_NO_ERROR; + + unlock: + unlock(folder); + free: + for(i = 0 ; i < carray_count(tab) ; i ++) + mailmessage_free(carray_get(tab, i)); + carray_free(tab); + err: + return res; +} + +static int release_read_mbox(struct mailmbox_folder * folder) +{ + int r; + + r = mailmbox_read_unlock(folder); + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int acquire_read_mbox(struct mailmbox_folder * folder) +{ + int r; + + r = mailmbox_validate_read_lock(folder); + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int release_write_mbox(struct mailmbox_folder * folder) +{ + int r; + + r = mailmbox_write_unlock(folder); + return mboxdriver_mbox_error_to_mail_error(r); +} + +static int acquire_write_mbox(struct mailmbox_folder * folder) +{ + int r; + int res; + + r = mailmbox_validate_write_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto err; + } + + if (folder->mb_written_uid < folder->mb_max_uid) { + r = mailmbox_expunge_no_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = mboxdriver_mbox_error_to_mail_error(r); + goto unlock; + } + } + + return MAIL_NO_ERROR; + + unlock: + mailmbox_write_unlock(folder); + err: + return res; +} + +/* get message list with all valid written UID */ + +int mbox_get_uid_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + return mbox_get_locked_messages_list(folder, session, driver, + acquire_write_mbox, release_write_mbox, result); +} + + +/* get message list */ + +int mbox_get_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + return mbox_get_locked_messages_list(folder, session, driver, + acquire_read_mbox, release_read_mbox, result); +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_tools.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_tools.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,85 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_tools.h,v 1.10 2004/11/21 21:53:32 hoa Exp $ + */ + +#ifndef MBOXDRIVER_TOOLS_H + +#define MBOXDRIVER_TOOLS_H + +#include "mail_cache_db_types.h" +#include "mboxdriver_types.h" +#include "mailmbox.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mboxdriver_mbox_error_to_mail_error(int error); + +int mboxdriver_fetch_msg(mailsession * session, uint32_t index, + char ** result, size_t * result_len); + +int mboxdriver_fetch_size(mailsession * session, uint32_t index, + size_t * result); + +int +mboxdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result); + +int +mboxdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, struct mail_flags * flags); + +int mbox_get_uid_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result); + +int mbox_get_messages_list(struct mailmbox_folder * folder, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result); + +int mboxdriver_fetch_header(mailsession * session, uint32_t index, + char ** result, size_t * result_len); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxdriver_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,107 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxdriver_types.h,v 1.7 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MBOXDRIVER_TYPES_H + +#define MBOXDRIVER_TYPES_H + +#include <libetpan/maildriver_types.h> +#include <libetpan/mailmbox.h> +#include <libetpan/mailstorage_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* mbox driver */ + +enum { + MBOXDRIVER_SET_READ_ONLY = 1, + MBOXDRIVER_SET_NO_UID +}; + +struct mbox_session_state_data { + struct mailmbox_folder * mbox_folder; + int mbox_force_read_only; + int mbox_force_no_uid; +}; + +/* cached version */ + +enum { + /* the mapping of the parameters should be the same as for mbox */ + MBOXDRIVER_CACHED_SET_READ_ONLY = 1, + MBOXDRIVER_CACHED_SET_NO_UID, + /* cache specific */ + MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY, + MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY +}; + +struct mbox_cached_session_state_data { + mailsession * mbox_ancestor; + char * mbox_quoted_mb; + char mbox_cache_directory[PATH_MAX]; + char mbox_flags_directory[PATH_MAX]; + struct mail_flags_store * mbox_flags_store; +}; + +/* mbox storage */ + +/* + mbox_mailstorage is the state data specific to the mbox storage. + + - pathname is the filename that contains the mailbox. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct mbox_mailstorage { + char * mbox_pathname; + + int mbox_cached; + char * mbox_cache_directory; + char * mbox_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxstorage.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxstorage.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,204 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxstorage.c,v 1.13 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mboxstorage.h" + +#include "mail.h" +#include "mailmessage.h" +#include "mboxdriver.h" +#include "mboxdriver_cached.h" +#include "maildriver.h" + +#include <stdlib.h> +#include <string.h> + +/* mbox storage */ + +static int mbox_mailstorage_connect(struct mailstorage * storage); +static int +mbox_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void mbox_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver mbox_mailstorage_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sto_name */ "mbox", + /* sto_connect */ mbox_mailstorage_connect, + /* sto_get_folder_session */ mbox_mailstorage_get_folder_session, + /* sto_uninitialize */ mbox_mailstorage_uninitialize, +#else + .sto_name = "mbox", + .sto_connect = mbox_mailstorage_connect, + .sto_get_folder_session = mbox_mailstorage_get_folder_session, + .sto_uninitialize = mbox_mailstorage_uninitialize, +#endif +}; + +LIBETPAN_EXPORT +int mbox_mailstorage_init(struct mailstorage * storage, + const char * mbox_pathname, int mbox_cached, + const char * mbox_cache_directory, const char * mbox_flags_directory) +{ + struct mbox_mailstorage * mbox_storage; + + mbox_storage = malloc(sizeof(* mbox_storage)); + if (mbox_storage == NULL) + goto err; + + mbox_storage->mbox_pathname = strdup(mbox_pathname); + if (mbox_storage->mbox_pathname == NULL) + goto free; + + mbox_storage->mbox_cached = mbox_cached; + + if (mbox_cached && (mbox_cache_directory != NULL) && + (mbox_flags_directory != NULL)) { + mbox_storage->mbox_cache_directory = strdup(mbox_cache_directory); + if (mbox_storage->mbox_cache_directory == NULL) + goto free_pathname; + + mbox_storage->mbox_flags_directory = strdup(mbox_flags_directory); + if (mbox_storage->mbox_flags_directory == NULL) + goto free_cache_directory; + } + else { + mbox_storage->mbox_cached = FALSE; + mbox_storage->mbox_cache_directory = NULL; + mbox_storage->mbox_flags_directory = NULL; + } + + storage->sto_data = mbox_storage; + storage->sto_driver = &mbox_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(mbox_storage->mbox_cache_directory); + free_pathname: + free(mbox_storage->mbox_pathname); + free: + free(mbox_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void mbox_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct mbox_mailstorage * mbox_storage; + + mbox_storage = storage->sto_data; + if (mbox_storage->mbox_flags_directory != NULL) + free(mbox_storage->mbox_flags_directory); + if (mbox_storage->mbox_cache_directory != NULL) + free(mbox_storage->mbox_cache_directory); + free(mbox_storage->mbox_pathname); + free(mbox_storage); + + storage->sto_data = NULL; +} + +static int mbox_mailstorage_connect(struct mailstorage * storage) +{ + struct mbox_mailstorage * mbox_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + mbox_storage = storage->sto_data; + + if (mbox_storage->mbox_cached) + driver = mbox_cached_session_driver; + else + driver = mbox_session_driver; + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (mbox_storage->mbox_cached) { + r = mailsession_parameters(session, + MBOXDRIVER_CACHED_SET_CACHE_DIRECTORY, + mbox_storage->mbox_cache_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + r = mailsession_parameters(session, + MBOXDRIVER_CACHED_SET_FLAGS_DIRECTORY, + mbox_storage->mbox_flags_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } + + r = mailsession_connect_path(session, mbox_storage->mbox_pathname); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int +mbox_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} + Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxstorage.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mbox/mboxstorage.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,70 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mboxstorage.h,v 1.8 2006/06/02 15:44:29 smarinier Exp $ + */ + +#ifndef MBOXSTORAGE_H + +#define MBOXSTORAGE_H + +#include <libetpan/mboxdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mbox_mailstorage_init is the constructor for a mbox storage. + + @param storage this is the storage to initialize. + + @param pathname is the filename that contains the mailbox. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +LIBETPAN_EXPORT +int mbox_mailstorage_init(struct mailstorage * storage, + const char * mb_pathname, int mb_cached, + const char * mb_cache_directory, const char * mb_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,30 @@ +top_builddir = ../../../.. + +HEADERS = \ + mhdriver.h \ + mhdriver_cached.h \ + mhdriver_cached_message.h \ + mhdriver_message.h \ + mhdriver_types.h \ + mhstorage.h + + +SOURCES = \ + mhdriver.c \ + mhdriver_cached.c \ + mhdriver_cached_message.c \ + mhdriver_message.c \ + mhdriver_tools.c \ + mhstorage.c + + +TARGET = libmh +INCLUDES = -I../../interface \ + -I../../tools \ + -I$(srcdir)/low-level/mh \ + -I$(srcdir)/low-level/mime \ + -I$(srcdir)/low-level/imf \ + -I$(srcdir)/data-types + + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,932 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver.c,v 1.34 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mhdriver.h" + +#include <stdio.h> +#include <sys/types.h> +#ifndef _MSC_VER +# include <dirent.h> +# include <unistd.h> +# include <sys/mman.h> +#endif +#include <sys/stat.h> +#include <ctype.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> + +#include "mailmh.h" +#include "maildriver_tools.h" +#include "mhdriver_tools.h" +#include "mhdriver_message.h" +#include "mailmessage.h" + +static int mhdriver_initialize(mailsession * session); + +static void mhdriver_uninitialize(mailsession * session); + +static int mhdriver_connect_path(mailsession * session, const char * path); +static int mhdriver_logout(mailsession * session); + +static int mhdriver_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result); +static int mhdriver_create_folder(mailsession * session, const char * mb); + +static int mhdriver_delete_folder(mailsession * session, const char * mb); + +static int mhdriver_rename_folder(mailsession * session, const char * mb, + const char * new_name); + +static int mhdriver_select_folder(mailsession * session, const char * mb); + +static int mhdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int mhdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int mhdriver_list_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int mhdriver_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int mhdriver_subscribe_folder(mailsession * session, const char * mb); + +static int mhdriver_unsubscribe_folder(mailsession * session, const char * mb); + +static int mhdriver_append_message(mailsession * session, + const char * message, size_t size); +static int mhdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); +static int mhdriver_copy_message(mailsession * session, + uint32_t num, const char * mb); + +static int mhdriver_remove_message(mailsession * session, uint32_t num); + +static int mhdriver_move_message(mailsession * session, + uint32_t num, const char * mb); + +static int mhdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int mhdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int mhdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_mh_session_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sess_name */ "mh", + + /* sess_initialize */ mhdriver_initialize, + /* sess_uninitialize */ mhdriver_uninitialize, + + /* sess_parameters */ NULL, + + /* sess_connect_stream */ NULL, + /* sess_connect_path */ mhdriver_connect_path, + /* sess_starttls */ NULL, + /* sess_login */ NULL, + /* sess_logout */ mhdriver_logout, + /* sess_noop */ NULL, + + /* sess_build_folder_name */ mhdriver_build_folder_name, + /* sess_create_folder */ mhdriver_create_folder, + /* sess_delete_folder */ mhdriver_delete_folder, + /* sess_rename_folder */ mhdriver_rename_folder, + /* sess_check_folder */ NULL, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ mhdriver_select_folder, + /* sess_expunge_folder */ NULL, + /* sess_status_folder */ mhdriver_status_folder, + /* sess_messages_number */ mhdriver_messages_number, + /* sess_recent_number */ mhdriver_messages_number, + /* sess_unseen_number */ mhdriver_messages_number, + /* sess_list_folders */ mhdriver_list_folders, + /* sess_lsub_folders */ mhdriver_lsub_folders, + /* sess_subscribe_folder */ mhdriver_subscribe_folder, + /* sess_unsubscribe_folder */ mhdriver_unsubscribe_folder, + + /* sess_append_message */ mhdriver_append_message, + /* sess_append_message_flags */ mhdriver_append_message_flags, + /* sess_copy_message */ mhdriver_copy_message, + /* sess_move_message */ mhdriver_move_message, + + /* sess_get_message */ mhdriver_get_message, + /* sess_get_message_by_uid */ mhdriver_get_message_by_uid, + + /* sess_get_messages_list */ mhdriver_get_messages_list, + /* sess_get_envelopes_list */ maildriver_generic_get_envelopes_list, + /* sess_remove_message */ mhdriver_remove_message, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL, + +#else + .sess_name = "mh", + + .sess_initialize = mhdriver_initialize, + .sess_uninitialize = mhdriver_uninitialize, + + .sess_parameters = NULL, + + .sess_connect_stream = NULL, + .sess_connect_path = mhdriver_connect_path, + .sess_starttls = NULL, + .sess_login = NULL, + .sess_logout = mhdriver_logout, + .sess_noop = NULL, + + .sess_build_folder_name = mhdriver_build_folder_name, + .sess_create_folder = mhdriver_create_folder, + .sess_delete_folder = mhdriver_delete_folder, + .sess_rename_folder = mhdriver_rename_folder, + .sess_check_folder = NULL, + .sess_examine_folder = NULL, + .sess_select_folder = mhdriver_select_folder, + .sess_expunge_folder = NULL, + .sess_status_folder = mhdriver_status_folder, + .sess_messages_number = mhdriver_messages_number, + .sess_recent_number = mhdriver_messages_number, + .sess_unseen_number = mhdriver_messages_number, + .sess_list_folders = mhdriver_list_folders, + .sess_lsub_folders = mhdriver_lsub_folders, + .sess_subscribe_folder = mhdriver_subscribe_folder, + .sess_unsubscribe_folder = mhdriver_unsubscribe_folder, + + .sess_append_message = mhdriver_append_message, + .sess_append_message_flags = mhdriver_append_message_flags, + .sess_copy_message = mhdriver_copy_message, + .sess_move_message = mhdriver_move_message, + + .sess_get_messages_list = mhdriver_get_messages_list, + .sess_get_envelopes_list = maildriver_generic_get_envelopes_list, + .sess_remove_message = mhdriver_remove_message, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = mhdriver_get_message, + .sess_get_message_by_uid = mhdriver_get_message_by_uid, + .sess_login_sasl = NULL, +#endif +}; + +mailsession_driver * mh_session_driver = &local_mh_session_driver; + +static inline struct mh_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct mailmh * get_mh_session(mailsession * session) +{ + return get_data(session)->mh_session; +} + +static inline struct mailmh_folder * get_mh_cur_folder(mailsession * session) +{ + return get_data(session)->mh_cur_folder; +} + +static int add_to_list(mailsession * session, const char * mb) +{ + char * new_mb; + struct mh_session_state_data * data; + int r; + + data = get_data(session); + + new_mb = strdup(mb); + if (new_mb == NULL) + return -1; + + r = clist_append(data->mh_subscribed_list, new_mb); + if (r < 0) { + free(new_mb); + return -1; + } + + return 0; +} + +static int remove_from_list(mailsession * session, const char * mb) +{ + clistiter * cur; + struct mh_session_state_data * data; + + data = get_data(session); + + for(cur = clist_begin(data->mh_subscribed_list) ; + cur != NULL ; cur = clist_next(cur)) { + char * cur_name; + + cur_name = clist_content(cur); + if (strcmp(cur_name, mb) == 0) { + clist_delete(data->mh_subscribed_list, cur); + free(cur_name); + return 0; + } + } + + return -1; +} + +static int mhdriver_initialize(mailsession * session) +{ + struct mh_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->mh_session = NULL; + data->mh_cur_folder = NULL; + + data->mh_subscribed_list = clist_new(); + if (data->mh_subscribed_list == NULL) + goto free; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void mhdriver_uninitialize(mailsession * session) +{ + struct mh_session_state_data * data; + + data = get_data(session); + + if (data->mh_session != NULL) + mailmh_free(data->mh_session); + + clist_foreach(data->mh_subscribed_list, (clist_func) free, NULL); + clist_free(data->mh_subscribed_list); + + free(data); + + session->sess_data = NULL; +} + + +static int mhdriver_connect_path(mailsession * session, const char * path) +{ + struct mailmh * mh; + + if (get_mh_session(session) != NULL) + return MAIL_ERROR_BAD_STATE; + + mh = mailmh_new(path); + if (mh == NULL) + return MAIL_ERROR_MEMORY; + + get_data(session)->mh_session = mh; + + return MAIL_NO_ERROR; +} + +static int mhdriver_logout(mailsession * session) +{ + struct mailmh * mh; + + mh = get_mh_session(session); + + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + mailmh_free(mh); + get_data(session)->mh_session = NULL; + + return MAIL_NO_ERROR; +} + +/* folders operations */ + +static int mhdriver_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result) +{ + char * folder_name; + + folder_name = malloc(strlen(mb) + 2 + strlen(name)); + if (folder_name == NULL) + return MAIL_ERROR_MEMORY; + + strcpy(folder_name, mb); + strcat(folder_name, "/"); + strcat(folder_name, name); + + * result = folder_name; + + return MAIL_NO_ERROR; +} + +static int get_parent(mailsession * session, const char * mb, + struct mailmh_folder ** result_folder, + const char ** result_name) +{ + const char * name; + size_t length; + size_t i; + char * parent_name; + struct mailmh_folder * parent; + struct mailmh * mh; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + length = strlen(mb); + for(i = length - 1 ; i >= 0 ; i--) + if (mb[i] == '/') + break; + name = mb + i + 1; + + parent_name = malloc(i + 1); + /* strndup(mb, i) */ + if (parent_name == NULL) + return MAIL_ERROR_MEMORY; + + strncpy(parent_name, mb, i); + parent_name[i] = '\0'; + + parent = mailmh_folder_find(mh->mh_main, parent_name); + free(parent_name); + if (parent == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + * result_folder = parent; + * result_name = name; + + return MAIL_NO_ERROR; +} + +static int mhdriver_create_folder(mailsession * session, const char * mb) +{ + int r; + struct mailmh_folder * parent; + char * name; + + r = get_parent(session, mb, &parent, &name); + if (r != MAIL_NO_ERROR) + return r; + + r = mailmh_folder_add_subfolder(parent, name); + + return mhdriver_mh_error_to_mail_error(r); +} + +static int mhdriver_delete_folder(mailsession * session, const char * mb) +{ + int r; + struct mailmh_folder * folder; + struct mailmh * mh; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + folder = mailmh_folder_find(mh->mh_main, mb); + if (folder == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + if (get_mh_cur_folder(session) == folder) + get_data(session)->mh_cur_folder = NULL; + + r = mailmh_folder_remove_subfolder(folder); + + return mhdriver_mh_error_to_mail_error(r); +} + +static int mhdriver_rename_folder(mailsession * session, const char * mb, + const char * new_name) +{ + struct mailmh_folder * src_folder; + struct mailmh_folder * dst_folder; + char * name; + struct mailmh * mh; + int r; + + r = get_parent(session, new_name, &dst_folder, &name); + if (r != MAIL_NO_ERROR) + return r; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + src_folder = mailmh_folder_find(mh->mh_main, mb); + if (src_folder == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + if (get_mh_cur_folder(session) == src_folder) + get_data(session)->mh_cur_folder = NULL; + + r = mailmh_folder_rename_subfolder(src_folder, dst_folder, name); + + return mhdriver_mh_error_to_mail_error(r); +} + +static int mhdriver_select_folder(mailsession * session, const char * mb) +{ + struct mailmh_folder * folder; + struct mailmh * mh; + int r; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmh_folder_update(mh->mh_main); + + folder = mailmh_folder_find(mh->mh_main, mb); + if (folder == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + get_data(session)->mh_cur_folder = folder; + r = mailmh_folder_update(folder); + + return mhdriver_mh_error_to_mail_error(r); +} + +static int mhdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + uint32_t count; + int r; + + r = mhdriver_messages_number(session, mb, &count); + if (r != MAIL_NO_ERROR) + return r; + + * result_messages = count; + * result_recent = count; + * result_unseen = count; + + return MAIL_NO_ERROR; +} + +static int mhdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + struct mailmh_folder * folder; + uint32_t count; + struct mailmh * mh; + unsigned int i; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + if (mb != NULL) { + folder = mailmh_folder_find(mh->mh_main, mb); + if (folder == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + } + else { + folder = get_mh_cur_folder(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + } + + mailmh_folder_update(folder); + count = 0; + for (i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) { + struct mailmh_msg_info * msg_info; + + msg_info = carray_get(folder->fl_msgs_tab, i); + if (msg_info != NULL) + count ++; + } + + * result = count; + + return MAIL_NO_ERROR; +} + + +static int get_list_folders(struct mailmh_folder * folder, clist ** result) +{ + unsigned int i; + clist * list; + char * new_filename; + int res; + int r; + + list = * result; + + new_filename = strdup(folder->fl_filename); + if (new_filename == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = mailmh_folder_update(folder); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + res = mhdriver_mh_error_to_mail_error(r); + goto free; + } + + r = clist_append(list, new_filename); + if (r < 0) { + free(new_filename); + res = MAIL_ERROR_MEMORY; + goto free; + } + + if (folder->fl_subfolders_tab != NULL) { + for(i = 0 ; i < carray_count(folder->fl_subfolders_tab) ; i++) { + struct mailmh_folder * subfolder; + + subfolder = carray_get(folder->fl_subfolders_tab, i); + + r = get_list_folders(subfolder, &list); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free; + } + } + } + + * result = list; + + return MAIL_NO_ERROR; + + free: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + return res; +} + + +static int mhdriver_list_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + clist * list; + int r; + struct mailmh * mh; + struct mail_list * ml; + + mh = get_mh_session(session); + + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + list = clist_new(); + if (list == NULL) + return MAIL_ERROR_MEMORY; + + r = get_list_folders(mh->mh_main, &list); + if (r != MAIL_NO_ERROR) + return r; + + ml = mail_list_new(list); + if (ml == NULL) + goto free; + + * result = ml; + + return MAIL_NO_ERROR; + + free: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + return MAIL_ERROR_MEMORY; +} + +static int mhdriver_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + clist * subscribed; + clist * lsub_result; + clistiter * cur; + struct mail_list * lsub; + size_t length; + int r; + + length = strlen(mb); + + subscribed = get_data(session)->mh_subscribed_list; + + lsub_result = clist_new(); + if (lsub_result == NULL) + return MAIL_ERROR_MEMORY; + + for(cur = clist_begin(subscribed) ; cur != NULL ; + cur = clist_next(cur)) { + char * cur_mb; + char * new_mb; + + cur_mb = clist_content(cur); + + if (strncmp(mb, cur_mb, length) == 0) { + new_mb = strdup(cur_mb); + if (new_mb == NULL) + goto free_list; + + r = clist_append(lsub_result, new_mb); + if (r < 0) { + free(new_mb); + goto free_list; + } + } + } + + lsub = mail_list_new(lsub_result); + if (lsub == NULL) + goto free_list; + + * result = lsub; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(lsub_result, (clist_func) free, NULL); + clist_free(lsub_result); + return MAIL_ERROR_MEMORY; +} + +static int mhdriver_subscribe_folder(mailsession * session, const char * mb) +{ + int r; + + r = add_to_list(session, mb); + if (r < 0) + return MAIL_ERROR_SUBSCRIBE; + + return MAIL_NO_ERROR; +} + +static int mhdriver_unsubscribe_folder(mailsession * session, const char * mb) +{ + int r; + + r = remove_from_list(session, mb); + if (r < 0) + return MAIL_ERROR_UNSUBSCRIBE; + + return MAIL_NO_ERROR; +} + +/* messages operations */ + +static int mhdriver_append_message(mailsession * session, + const char * message, size_t size) +{ + int r; + struct mailmh_folder * folder; + + folder = get_mh_cur_folder(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmh_folder_add_message(folder, message, size); + + switch (r) { + case MAILMH_ERROR_FILE: + return MAIL_ERROR_DISKSPACE; + + default: + return mhdriver_mh_error_to_mail_error(r); + } +} + +static int mhdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + return mhdriver_append_message(session, message, size); +} + +static int mhdriver_copy_message(mailsession * session, + uint32_t num, const char * mb) +{ + int fd; + int r; + struct mailmh_folder * folder; + struct mailmh * mh; + int res; + + mh = get_mh_session(session); + if (mh == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmh_folder_get_message_fd(folder, num, O_RDONLY, &fd); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + folder = mailmh_folder_find(mh->mh_main, mb); + if (folder == NULL) { + res = MAIL_ERROR_FOLDER_NOT_FOUND; + goto close; + } + + r = mailmh_folder_add_message_file(folder, fd); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_COPY; + goto close; + } + + close(fd); + + return MAIL_NO_ERROR; + + close: + close(fd); + err: + return res; +} + +static int mhdriver_remove_message(mailsession * session, uint32_t num) +{ + int r; + struct mailmh_folder * folder; + + folder = get_mh_cur_folder(session); + if (folder == NULL) + return MAIL_ERROR_DELETE; + + r = mailmh_folder_remove_message(folder, num); + + return mhdriver_mh_error_to_mail_error(r); +} + +static int mhdriver_move_message(mailsession * session, + uint32_t num, const char * mb) +{ + int r; + struct mailmh_folder * src_folder; + struct mailmh_folder * dest_folder; + struct mailmh * mh; + + mh = get_mh_session(session); + if (mh == NULL) + return MAIL_ERROR_BAD_STATE; + + src_folder = get_mh_cur_folder(session); + if (src_folder == NULL) + return MAIL_ERROR_BAD_STATE; + + dest_folder = mailmh_folder_find(mh->mh_main, mb); + if (dest_folder == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + r = mailmh_folder_move_message(dest_folder, src_folder, num); + + return mhdriver_mh_error_to_mail_error(r); +} + + +static int mhdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct mailmh_folder * folder; + int res; + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mailmh_folder_update(folder); + return mh_get_messages_list(folder, session, mh_message_driver, result); + + err: + return res; +} + +static int mhdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, mh_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int mhdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t index; + char *p; + struct mailmh_msg_info * mh_msg_info; + struct mh_session_state_data * mh_data; + chashdatum key; + chashdatum data; + int r; + time_t mtime; + char * mtime_p; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + index = strtoul(uid, &p, 10); + if (p == uid || * p != '-') + return MAIL_ERROR_INVAL; + + mh_data = session->sess_data; +#if 0 + mh_msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, index); +#endif + key.data = &index; + key.len = sizeof(index); + r = chash_get(mh_data->mh_cur_folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_MSG_NOT_FOUND; + + mh_msg_info = data.data; + + mtime_p = p + 1; + + mtime = strtoul(mtime_p, &p, 10); + if ((* p == '-') && (mtime == mh_msg_info->msg_mtime)) { + size_t size; + char *size_p; + + size_p = p + 1; + size = strtoul(size_p, &p, 10); + if ((* p == '\0') && (size == mh_msg_info->msg_size)) + return mhdriver_get_message(session, index, result); + } + else if (* p != '-') { + return MAIL_ERROR_INVAL; + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver.h,v 1.12 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef MHDRIVER_H + +#define MHDRIVER_H + +#include <libetpan/maildriver.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mh_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_cached.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_cached.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1375 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_cached.c,v 1.46 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mhdriver_cached.h" + +#include <stdio.h> +#include <sys/types.h> +#ifdef _MSC_VER +# include "win_etpan.h" +#else +# include <dirent.h> +# include <unistd.h> +# include <sys/mman.h> +#endif +#include <sys/stat.h> +#include <ctype.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> + +#include "mail.h" +#include "mail_cache_db.h" + +#include "generic_cache.h" +#include "imfcache.h" +#include "mhdriver.h" + +#include "mhdriver_cached_message.h" +#include "mailmh.h" +#include "maildriver_tools.h" +#include "mhdriver_tools.h" +#include "mailmessage.h" + +static int mhdriver_cached_initialize(mailsession * session); + +static void mhdriver_cached_uninitialize(mailsession * session); + +static int mhdriver_cached_parameters(mailsession * session, + int id, void * value); + +static int mhdriver_cached_connect_path(mailsession * session, const char * path); +static int mhdriver_cached_logout(mailsession * session); + +static int mhdriver_cached_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result); +static int mhdriver_cached_create_folder(mailsession * session, const char * mb); + +static int mhdriver_cached_delete_folder(mailsession * session, const char * mb); + +static int mhdriver_cached_rename_folder(mailsession * session, const char * mb, + const char * new_name); + +static int mhdriver_cached_check_folder(mailsession * session); + +static int mhdriver_cached_select_folder(mailsession * session, const char * mb); + +static int mhdriver_cached_expunge_folder(mailsession * session); + +static int mhdriver_cached_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int mhdriver_cached_messages_number(mailsession * session, const char * mb, + uint32_t * result); +static int mhdriver_cached_recent_number(mailsession * session, const char * mb, + uint32_t * result); +static int mhdriver_cached_unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +static int mhdriver_cached_list_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int mhdriver_cached_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int mhdriver_cached_subscribe_folder(mailsession * session, const char * mb); + +static int mhdriver_cached_unsubscribe_folder(mailsession * session, + const char * mb); + +static int mhdriver_cached_append_message(mailsession * session, + const char * message, size_t size); +static int mhdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); +static int mhdriver_cached_copy_message(mailsession * session, + uint32_t num, const char * mb); + +static int mhdriver_cached_remove_message(mailsession * session, + uint32_t num); + +static int mhdriver_cached_move_message(mailsession * session, + uint32_t num, const char * mb); + +static int +mhdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +mhdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int mhdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int mhdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_mh_cached_session_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sess_name */ "mh-cached", + + /* sess_initialize */ mhdriver_cached_initialize, + /* sess_uninitialize */ mhdriver_cached_uninitialize, + + /* sess_parameters */ mhdriver_cached_parameters, + + /* sess_connect_stream */ NULL, + /* sess_connect_path */ mhdriver_cached_connect_path, + /* sess_starttls */ NULL, + /* sess_login */ NULL, + /* sess_logout */ mhdriver_cached_logout, + /* sess_noop */ NULL, + + /* sess_build_folder_name */ mhdriver_cached_build_folder_name, + /* sess_create_folder */ mhdriver_cached_create_folder, + /* sess_delete_folder */ mhdriver_cached_delete_folder, + /* sess_rename_folder */ mhdriver_cached_rename_folder, + /* sess_check_folder */ mhdriver_cached_check_folder, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ mhdriver_cached_select_folder, + /* sess_expunge_folder */ mhdriver_cached_expunge_folder, + /* sess_status_folder */ mhdriver_cached_status_folder, + /* sess_messages_number */ mhdriver_cached_messages_number, + /* sess_recent_number */ mhdriver_cached_recent_number, + /* sess_unseen_number */ mhdriver_cached_unseen_number, + /* sess_list_folders */ mhdriver_cached_list_folders, + /* sess_lsub_folders */ mhdriver_cached_lsub_folders, + /* sess_subscribe_folder */ mhdriver_cached_subscribe_folder, + /* sess_unsubscribe_folder */ mhdriver_cached_unsubscribe_folder, + + /* sess_append_message */ mhdriver_cached_append_message, + /* sess_append_message_flags */ mhdriver_cached_append_message_flags, + /* sess_copy_message */ mhdriver_cached_copy_message, + /* sess_move_message */ mhdriver_cached_move_message, + + /* sess_get_message */ mhdriver_cached_get_message, + /* sess_get_message_by_uid */ mhdriver_cached_get_message_by_uid, + + /* sess_get_messages_list */ mhdriver_cached_get_messages_list, + /* sess_get_envelopes_list */ mhdriver_cached_get_envelopes_list, + /* sess_remove_message */ mhdriver_cached_remove_message, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL, + +#else + .sess_name = "mh-cached", + + .sess_initialize = mhdriver_cached_initialize, + .sess_uninitialize = mhdriver_cached_uninitialize, + + .sess_parameters = mhdriver_cached_parameters, + + .sess_connect_stream = NULL, + .sess_connect_path = mhdriver_cached_connect_path, + .sess_starttls = NULL, + .sess_login = NULL, + .sess_logout = mhdriver_cached_logout, + .sess_noop = NULL, + + .sess_build_folder_name = mhdriver_cached_build_folder_name, + .sess_create_folder = mhdriver_cached_create_folder, + .sess_delete_folder = mhdriver_cached_delete_folder, + .sess_rename_folder = mhdriver_cached_rename_folder, + .sess_check_folder = mhdriver_cached_check_folder, + .sess_examine_folder = NULL, + .sess_select_folder = mhdriver_cached_select_folder, + .sess_expunge_folder = mhdriver_cached_expunge_folder, + .sess_status_folder = mhdriver_cached_status_folder, + .sess_messages_number = mhdriver_cached_messages_number, + .sess_recent_number = mhdriver_cached_recent_number, + .sess_unseen_number = mhdriver_cached_unseen_number, + .sess_list_folders = mhdriver_cached_list_folders, + .sess_lsub_folders = mhdriver_cached_lsub_folders, + .sess_subscribe_folder = mhdriver_cached_subscribe_folder, + .sess_unsubscribe_folder = mhdriver_cached_unsubscribe_folder, + + .sess_append_message = mhdriver_cached_append_message, + .sess_append_message_flags = mhdriver_cached_append_message_flags, + .sess_copy_message = mhdriver_cached_copy_message, + .sess_move_message = mhdriver_cached_move_message, + + .sess_get_messages_list = mhdriver_cached_get_messages_list, + .sess_get_envelopes_list = mhdriver_cached_get_envelopes_list, + .sess_remove_message = mhdriver_cached_remove_message, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = mhdriver_cached_get_message, + .sess_get_message_by_uid = mhdriver_cached_get_message_by_uid, + .sess_login_sasl = NULL, +#endif +}; + +mailsession_driver * mh_cached_session_driver = +&local_mh_cached_session_driver; + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + + +static inline struct mh_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->mh_ancestor; +} + +static inline struct mh_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + +static inline struct mailmh * +get_mh_session(mailsession * session) +{ + return get_ancestor_data(session)->mh_session; +} + +static inline struct mailmh_folder * +get_mh_cur_folder(mailsession * session) +{ + return get_ancestor_data(session)->mh_cur_folder; +} + + +#define FILENAME_MAX_UID "max-uid" + +/* write max uid current value */ + +static int write_max_uid_value(mailsession * session) +{ + int r; + char filename[PATH_MAX]; + FILE * f; + int res; + struct mh_cached_session_state_data * cached_data; + struct mh_session_state_data * ancestor_data; + int fd; + + MMAPString * mmapstr; + size_t cur_token; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + if (cached_data->mh_quoted_mb == NULL) + return MAIL_ERROR_BAD_STATE; + + snprintf(filename, PATH_MAX, "%s/%s/%s", + cached_data->mh_cache_directory, + cached_data->mh_quoted_mb, FILENAME_MAX_UID); + + fd = creat(filename, S_IRUSR | S_IWUSR); + if (fd < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + f = fdopen(fd, "w"); + if (f == NULL) { + close(fd); + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close; + } + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mailimf_cache_int_write(mmapstr, &cur_token, + ancestor_data->mh_cur_folder->fl_max_index); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + fwrite(mmapstr->str, 1, mmapstr->len, f); + + mmap_string_free(mmapstr); + fclose(f); + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close: + fclose(f); + err: + return res; +} + +static int read_max_uid_value(mailsession * session) +{ + int r; + char filename[PATH_MAX]; + FILE * f; + uint32_t written_uid; + int res; + struct mh_cached_session_state_data * cached_data; + struct mh_session_state_data * ancestor_data; + + MMAPString * mmapstr; + size_t cur_token; + char buf[sizeof(uint32_t)]; + size_t read_size; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + snprintf(filename, PATH_MAX, "%s/%s/%s", + cached_data->mh_cache_directory, + cached_data->mh_quoted_mb, FILENAME_MAX_UID); + + f = fopen(filename, "r"); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + read_size = fread(buf, 1, sizeof(uint32_t), f); + + mmapstr = mmap_string_new_len(buf, read_size); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close; + } + + cur_token = 0; + + r = mailimf_cache_int_read(mmapstr, &cur_token, &written_uid); + if (r != MAIL_NO_ERROR) { + fclose(f); + res = r; + goto free_mmapstr; + } + + mmap_string_free(mmapstr); + fclose(f); + + if (written_uid > ancestor_data->mh_cur_folder->fl_max_index) + ancestor_data->mh_cur_folder->fl_max_index = written_uid; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close: + fclose(f); + err: + return res; +} + + +static int mhdriver_cached_initialize(mailsession * session) +{ + struct mh_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->mh_flags_store = mail_flags_store_new(); + if (data->mh_flags_store == NULL) + goto free; + + data->mh_ancestor = mailsession_new(mh_session_driver); + if (data->mh_ancestor == NULL) + goto free_store; + + data->mh_quoted_mb = NULL; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_store: + mail_flags_store_free(data->mh_flags_store); + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static void free_state(struct mh_cached_session_state_data * mh_data) +{ + if (mh_data->mh_quoted_mb) { + free(mh_data->mh_quoted_mb); + mh_data->mh_quoted_mb = NULL; + } +} + +static int mh_flags_store_process(char * flags_directory, char * quoted_mb, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + if (quoted_mb == NULL) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + flags_directory, quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = mhdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void mhdriver_cached_uninitialize(mailsession * session) +{ + struct mh_cached_session_state_data * data; + + data = get_cached_data(session); + + mh_flags_store_process(data->mh_flags_directory, data->mh_quoted_mb, + data->mh_flags_store); + + mail_flags_store_free(data->mh_flags_store); + + free_state(data); + mailsession_free(data->mh_ancestor); + free(data); + + session->sess_data = NULL; +} + +static int mhdriver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct mh_cached_session_state_data * cached_data; + int r; + + cached_data = get_cached_data(session); + + switch (id) { + case MHDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(cached_data->mh_cache_directory, value, PATH_MAX); + cached_data->mh_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(cached_data->mh_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case MHDRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(cached_data->mh_flags_directory, value, PATH_MAX); + cached_data->mh_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(cached_data->mh_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + } + + return MAIL_ERROR_INVAL; +} + +static int mhdriver_cached_connect_path(mailsession * session, const char * path) +{ + return mailsession_connect_path(get_ancestor(session), path); +} + +static int mhdriver_cached_logout(mailsession * session) +{ + int r; + struct mh_cached_session_state_data * cached_data; + + r = write_max_uid_value(session); + + cached_data = get_cached_data(session); + + mh_flags_store_process(cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, + cached_data->mh_flags_store); + + return mailsession_logout(get_ancestor(session)); +} + +static int mhdriver_cached_check_folder(mailsession * session) +{ + struct mh_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + mh_flags_store_process(cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, + cached_data->mh_flags_store); + + return MAIL_NO_ERROR; +} + +/* folders operations */ + +static int mhdriver_cached_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result) +{ + return mailsession_build_folder_name(get_ancestor(session), + mb, name, result); +} + +static int mhdriver_cached_create_folder(mailsession * session, const char * mb) +{ + return mailsession_create_folder(get_ancestor(session), mb); +} + +static int mhdriver_cached_delete_folder(mailsession * session, const char * mb) +{ + return mailsession_delete_folder(get_ancestor(session), mb); +} + +static int mhdriver_cached_rename_folder(mailsession * session, const char * mb, + const char * new_name) +{ + return mailsession_rename_folder(get_ancestor(session), mb, new_name); +} + +static int get_cache_directory(mailsession * session, + const char * path, char ** result) +{ + char * quoted_mb; + char dirname[PATH_MAX]; + int res; + int r; + struct mh_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + quoted_mb = maildriver_quote_mailbox(path); + if (quoted_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(dirname, PATH_MAX, "%s/%s", + cached_data->mh_cache_directory, quoted_mb); + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + snprintf(dirname, PATH_MAX, "%s/%s", + cached_data->mh_flags_directory, quoted_mb); + + r = generic_cache_create_dir(dirname); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + * result = quoted_mb; + + return MAIL_NO_ERROR; + + free: + free(quoted_mb); + err: + return res; +} + +static int mhdriver_cached_select_folder(mailsession * session, const char * mb) +{ + int r; + int res; + char * quoted_mb; + struct mh_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + mh_flags_store_process(cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, + cached_data->mh_flags_store); + + quoted_mb = NULL; + r = get_cache_directory(session, mb, "ed_mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailsession_select_folder(get_ancestor(session), mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + r = write_max_uid_value(session); + + free_state(cached_data); + cached_data->mh_quoted_mb = quoted_mb; + + r = read_max_uid_value(session); + + return MAIL_NO_ERROR; + + free: + free(quoted_mb); + err: + return res; +} + +static int mhdriver_cached_expunge_folder(mailsession * session) +{ + struct mailmh_folder * folder; + int res; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + struct mh_cached_session_state_data * cached_data; + unsigned int i; + int r; + + cached_data = get_cached_data(session); + if (cached_data->mh_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mh_flags_store_process(cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, + cached_data->mh_flags_store); + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mh_flags_directory, cached_data->mh_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { + struct mailmh_msg_info * mh_info; + struct mail_flags * flags; + + mh_info = carray_get(folder->fl_msgs_tab, i); + if (mh_info == NULL) + continue; + + r = mhdriver_get_cached_flags(cache_db_flags, mmapstr, + session, mh_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) + continue; + + if (flags->fl_flags & MAIL_FLAG_DELETED) { + r = mailmh_folder_remove_message(folder, mh_info->msg_index); + } + + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mailmh_folder_update(folder); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + + +static int mhdriver_cached_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen) +{ + struct mailmh_folder * folder; + int res; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + struct mh_cached_session_state_data * cached_data; + unsigned int i; + int r; + uint32_t count; + uint32_t recent; + uint32_t unseen; + + r = mhdriver_cached_select_folder(session, mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + count = 0; + recent = 0; + unseen = 0; + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + cached_data = get_cached_data(session); + if (cached_data->mh_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { + struct mailmh_msg_info * mh_info; + struct mail_flags * flags; + + mh_info = carray_get(folder->fl_msgs_tab, i); + if (mh_info == NULL) + continue; + + count ++; + + r = mhdriver_get_cached_flags(cache_db_flags, mmapstr, + session, mh_info->msg_index, + &flags); + + if (r != MAIL_NO_ERROR) { + recent ++; + unseen ++; + continue; + } + + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + * result_messages = count; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mhdriver_cached_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + return mailsession_messages_number(get_ancestor(session), mb, result); +} + +static int mhdriver_cached_recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = mhdriver_cached_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + + +static int mhdriver_cached_unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = mhdriver_cached_status_folder(session, mb, &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + + +static int mhdriver_cached_list_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + return mailsession_list_folders(get_ancestor(session), mb, result); +} + +static int mhdriver_cached_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + return mailsession_lsub_folders(get_ancestor(session), mb, result); +} + +static int mhdriver_cached_subscribe_folder(mailsession * session, const char * mb) +{ + return mailsession_subscribe_folder(get_ancestor(session), mb); +} + +static int mhdriver_cached_unsubscribe_folder(mailsession * session, + const char * mb) +{ + return mailsession_unsubscribe_folder(get_ancestor(session), mb); +} + +/* messages operations */ + +static int mhdriver_cached_append_message(mailsession * session, + const char * message, size_t size) +{ + return mhdriver_cached_append_message_flags(session, + message, size, NULL); +} + +static int mhdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + int r; + struct mailmh_folder * folder; + struct mailmh_msg_info * msg_info; + chashdatum key; + chashdatum value; + uint32_t uid; + struct mh_cached_session_state_data * data; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + char keyname[PATH_MAX]; + + folder = get_mh_cur_folder(session); + if (folder == NULL) + return MAIL_ERROR_BAD_STATE; + + r = mailmh_folder_add_message_uid(folder, + message, size, &uid); + + switch (r) { + case MAILMH_ERROR_FILE: + return MAIL_ERROR_DISKSPACE; + + case MAILMH_NO_ERROR: + break; + + default: + return mhdriver_mh_error_to_mail_error(r); + } + + if (flags == NULL) + goto exit; + + key.data = &uid; + key.len = sizeof(uid); + r = chash_get(folder->fl_msgs_hash, &key, &value); + if (r < 0) + return MAIL_ERROR_CACHE_MISS; + + msg_info = value.data; + + data = get_cached_data(session); + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + data->mh_flags_directory, data->mh_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) + goto exit; + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) + goto close_db_flags; + + snprintf(keyname, PATH_MAX, "%u-%lu-%lu-flags", + uid, (unsigned long) msg_info->msg_mtime, + (unsigned long) msg_info->msg_size); + + r = mhdriver_write_cached_flags(cache_db_flags, mmapstr, keyname, flags); + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + if (r != MAIL_NO_ERROR) + goto exit; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + exit: + return MAIL_NO_ERROR; +} + +static int mhdriver_cached_copy_message(mailsession * session, + uint32_t num, const char * mb) +{ + return mailsession_copy_message(get_ancestor(session), num, mb); +} + +static int mhdriver_cached_remove_message(mailsession * session, uint32_t num) +{ + return mailsession_remove_message(get_ancestor(session), num); +} + +static int mhdriver_cached_move_message(mailsession * session, + uint32_t num, const char * mb) +{ + return mailsession_move_message(get_ancestor(session), num, mb); +} + +static int +mhdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + struct mailmh_folder * folder; + int res; + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + return mh_get_messages_list(folder, session, + mh_cached_message_driver, result); + + err: + return res; +} + + + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mailimf_fields * fields; + int res; + struct mailmh_folder * folder; + struct mailmh_msg_info * msg_info; + chashdatum key; + chashdatum data; + + folder = get_mh_cur_folder(session); + +#if 0 + msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, num); + if (msg_info == NULL) + return MAIL_ERROR_CACHE_MISS; +#endif + key.data = # + key.len = sizeof(num); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_CACHE_MISS; + msg_info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%lu-%lu-envelope", + num, (unsigned long) msg_info->msg_mtime, + (unsigned long) msg_info->msg_size); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields * fields) +{ + int r; + char keyname[PATH_MAX]; + int res; + struct mailmh_folder * folder; + chashdatum key; + chashdatum data; + struct mailmh_msg_info * msg_info; + + folder = get_mh_cur_folder(session); +#if 0 + msg_info = cinthash_find(mh_data->mh_cur_folder->fl_msgs_hash, num); + if (msg_info == NULL) { + res = MAIL_ERROR_CACHE_MISS; + goto err; + } +#endif + key.data = # + key.len = sizeof(num); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_CACHE_MISS; + msg_info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%lu-%lu-envelope", + num, (unsigned long) msg_info->msg_mtime, + (unsigned long) msg_info->msg_size); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +mhdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + int res; + struct mh_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + if (cached_data->mh_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + mh_flags_store_process(cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, + cached_data->mh_flags_store); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename_env, PATH_MAX, "%s/%s/%s", + cached_data->mh_cache_directory, + cached_data->mh_quoted_mb, ENV_NAME); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mh_flags_directory, cached_data->mh_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto close_db_env; + } + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + struct mail_flags * flags; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, + msg->msg_session, msg->msg_index, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + + if (msg->msg_flags == NULL) { + r = mhdriver_get_cached_flags(cache_db_flags, mmapstr, + session, msg->msg_index, &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto close_db_env; + } + + /* add flags */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) + msg->msg_flags = mail_flags_new_empty(); + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = mhdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + mmap_string_free(mmapstr); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int mhdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, mh_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int mhdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t index; + char *p; + struct mailmh_msg_info * mh_msg_info; + struct mailmh_folder * folder; + time_t mtime; + char * mtime_p; + chashdatum key; + chashdatum data; + int r; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + index = strtoul(uid, &p, 10); + if (p == uid || * p != '-') + return MAIL_ERROR_INVAL; + + folder = get_mh_cur_folder(session); + + mh_msg_info = NULL; + key.data = &index; + key.len = sizeof(index); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_MSG_NOT_FOUND; + + mh_msg_info = data.data; + + mtime_p = p + 1; + + mtime = strtoul(mtime_p, &p, 10); + if ((* p == '-') && (mtime == mh_msg_info->msg_mtime)) { + size_t size; + char *size_p; + + size_p = p + 1; + size = strtoul(size_p, &p, 10); + if ((* p == '\0') && (size == mh_msg_info->msg_size)) + return mhdriver_cached_get_message(session, index, result); + } + else if (*p != '-') { + return MAIL_ERROR_INVAL; + } + + return MAIL_ERROR_MSG_NOT_FOUND; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_cached.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_cached.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_cached.h,v 1.10 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef MHDRIVER_CACHED_H + +#define MHDRIVER_CACHED_H + +#include <libetpan/mhdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * mh_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_cached_message.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_cached_message.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,371 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_cached_message.c,v 1.24 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mhdriver_message.h" + +#include "mailmessage_tools.h" +#include "mhdriver_tools.h" +#include "mhdriver_cached.h" +#include "mailmh.h" +#include "generic_cache.h" + +#include "mail_cache_db.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> + +static int mh_prefetch(mailmessage * msg_info); + +static void mh_prefetch_free(struct generic_message_t * msg); + +static int mh_initialize(mailmessage * msg_info); + +static int mh_fetch_size(mailmessage * msg_info, + size_t * result); + +static int mh_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static void mh_uninitialize(mailmessage * msg_info); + +static void mh_flush(mailmessage * msg_info); + +static void mh_check(mailmessage * msg_info); + +static int mh_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static mailmessage_driver local_mh_cached_message_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* msg_name */ "mh-cached", + + /* msg_initialize */ mh_initialize, + /* msg_uninitialize */ mh_uninitialize, + + /* msg_flush */ mh_flush, + /* msg_check */ mh_check, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mh_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ mh_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ mh_get_flags, +#else + .msg_name = "mh-cached", + + .msg_initialize = mh_initialize, + .msg_uninitialize = mh_uninitialize, + + .msg_flush = mh_flush, + .msg_check = mh_check, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mh_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = mh_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = mh_get_flags, +#endif +}; + +mailmessage_driver * mh_cached_message_driver = +&local_mh_cached_message_driver; + +static inline struct mh_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailsession * get_ancestor_session(mailmessage * msg) +{ + return get_cached_session_data(msg)->mh_ancestor; +} + +static inline struct mh_session_state_data * +get_ancestor_session_data(mailmessage * msg) +{ + return get_ancestor_session(msg)->sess_data; +} + +static inline struct mailmh * +get_mh_session(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->mh_session; +} + +static inline struct mailmh_folder * +get_mh_cur_folder(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->mh_cur_folder; +} + +static int mh_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + r = mhdriver_fetch_message(get_ancestor_session(msg_info), + msg_info->msg_index, &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void mh_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int mh_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[PATH_MAX]; + struct mailmh_msg_info * mh_msg_info; + chashdatum key; + chashdatum data; + struct mailmh_folder * folder; + + folder = get_mh_cur_folder(msg_info); + + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_INVAL; + + mh_msg_info = data.data; + + snprintf(static_uid, PATH_MAX, "%u-%lu-%lu", msg_info->msg_index, + mh_msg_info->msg_mtime, (unsigned long) mh_msg_info->msg_size); + uid = strdup(static_uid); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = mh_prefetch; + msg->msg_prefetch_free = mh_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + +static void mh_uninitialize(mailmessage * msg_info) +{ + mailmessage_generic_uninitialize(msg_info); +} + + +#define FLAGS_NAME "flags.db" + +static void mh_flush(mailmessage * msg_info) +{ + mailmessage_generic_flush(msg_info); +} + +static void mh_check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_cached_session_data(msg_info)->mh_flags_store, + msg_info); + /* ignore errors */ + } +} + +static int mh_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + size_t size; + + r = mhdriver_fetch_size(get_ancestor_session(msg_info), + msg_info->msg_index, &size); + if (r != MAIL_NO_ERROR) + return r; + + * result = size; + + return MAIL_NO_ERROR; +} + +static int mh_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + int res; + struct mh_cached_session_state_data * cached_data; + MMAPString * mmapstr; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; + } + + cached_data = get_cached_session_data(msg_info); + + flags = mail_flags_store_get(cached_data->mh_flags_store, + msg_info->msg_index); + + if (flags == NULL) { + if (cached_data->mh_quoted_mb == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->mh_flags_directory, + cached_data->mh_quoted_mb, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + r = mhdriver_get_cached_flags(cache_db_flags, mmapstr, + msg_info->msg_session, msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + flags = mail_flags_new_empty(); + if (flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int mh_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + msg = msg_info->msg_data; + if (msg->msg_message != NULL) { + return mailmessage_generic_fetch_header(msg_info, result, result_len); + } + else { + r = mhdriver_fetch_header(get_ancestor_session(msg_info), + msg_info->msg_index, &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; + } +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_cached_message.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_cached_message.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_cached_message.h,v 1.6 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef MHDRIVER_CACHED_MESSAGE_H + +#define MHDRIVER_CACHED_MESSAGE_H + +#include <libetpan/mhdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mh_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_message.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_message.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,246 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_message.c,v 1.22 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mhdriver_message.h" + +#include "mailmessage_tools.h" +#include "mhdriver_tools.h" +#include "mhdriver.h" +#include "mailmh.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> + +static int mh_prefetch(mailmessage * msg_info); + +static void mh_prefetch_free(struct generic_message_t * msg); + +static int mh_initialize(mailmessage * msg_info); + +static int mh_fetch_size(mailmessage * msg_info, + size_t * result); + +static int mh_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static mailmessage_driver local_mh_message_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* msg_name */ "mh", + + /* msg_initialize */ mh_initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ NULL, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ mh_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ mh_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ NULL, +#else + .msg_name = "mh", + + .msg_initialize = mh_initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = NULL, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = mh_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = mh_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = NULL, +#endif +}; + +mailmessage_driver * mh_message_driver = &local_mh_message_driver; + +static int mh_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + r = mhdriver_fetch_message(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void mh_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static inline struct mh_session_state_data * get_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline struct mailmh_folder * get_mh_cur_folder(mailmessage * msg) +{ + return get_data(msg)->mh_cur_folder; +} + +static int mh_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[PATH_MAX]; + struct mailmh_msg_info * mh_msg_info; + chashdatum key; + chashdatum value; + + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + r = chash_get(get_mh_cur_folder(msg_info)->fl_msgs_hash, &key, &value); + if (r < 0) + return MAIL_ERROR_INVAL; + + mh_msg_info = value.data; + + snprintf(static_uid, PATH_MAX, "%u-%lu-%lu", msg_info->msg_index, + (unsigned long) mh_msg_info->msg_mtime, + (unsigned long) mh_msg_info->msg_size); + uid = strdup(static_uid); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = mh_prefetch; + msg->msg_prefetch_free = mh_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + + +static int mh_fetch_size(mailmessage * msg_info, + size_t * result) +{ + int r; + size_t size; + + r = mhdriver_fetch_size(msg_info->msg_session, msg_info->msg_index, &size); + if (r != MAIL_NO_ERROR) + return r; + + * result = size; + + return MAIL_NO_ERROR; +} + + + + +static int mh_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + int r; + char * msg_content; + size_t msg_length; + + msg = msg_info->msg_data; + if (msg->msg_message != NULL) { + + r = mailmessage_generic_fetch_header(msg_info, result, result_len); + return r; + } + else { + r = mhdriver_fetch_header(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; + } +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_message.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_message.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_message.h,v 1.6 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef MHDRIVER_MESSAGE_H + +#define MHDRIVER_MESSAGE_H + +#include <libetpan/mhdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * mh_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_tools.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_tools.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,497 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_tools.c,v 1.25 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mhdriver_tools.h" + +#include "mailmessage.h" +#include "mhdriver.h" +#include "mhdriver_cached.h" +#include "maildriver_types.h" +#include "mailmh.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mail_cache_db.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> +#ifdef _MSC_VER +# include "win_etpan.h" +#endif + +int mhdriver_mh_error_to_mail_error(int error) +{ + switch (error) { + case MAILMH_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILMH_ERROR_FOLDER: + return MAIL_ERROR_FOLDER; + + case MAILMH_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILMH_ERROR_FILE: + return MAIL_ERROR_FILE; + + case MAILMH_ERROR_COULD_NOT_ALLOC_MSG: + return MAIL_ERROR_APPEND; + + case MAILMH_ERROR_RENAME: + return MAIL_ERROR_RENAME; + + case MAILMH_ERROR_MSG_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + default: + return MAIL_ERROR_INVAL; + } +} + + +static inline struct mh_session_state_data * get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline struct mailmh_folder * get_mh_cur_folder(mailsession * session) +{ + return get_data(session)->mh_cur_folder; +} + +static inline struct mh_cached_session_state_data * +cached_get_data(mailsession * session) +{ + return session->sess_data; +} + + +static inline mailsession * cached_get_ancestor(mailsession * session) +{ + return cached_get_data(session)->mh_ancestor; +} + +static inline struct mh_session_state_data * +cached_get_ancestor_data(mailsession * session) +{ + return get_data(cached_get_ancestor(session)); +} + +static inline struct mailmh_folder * +cached_get_mh_cur_folder(mailsession * session) +{ + return get_mh_cur_folder(cached_get_ancestor(session)); +} + +int mhdriver_fetch_message(mailsession * session, uint32_t index, + char ** result, size_t * result_len) +{ + size_t size; + size_t cur_token; + struct mailmh_folder * folder; + int fd; + MMAPString * mmapstr; + char * str; + int res; + int r; + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmh_folder_get_message_fd(folder, index, O_RDONLY, &fd); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + res = mhdriver_mh_error_to_mail_error(r); + goto close; + } + + r = mhdriver_fetch_size(session, index, &size); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + res = mhdriver_mh_error_to_mail_error(r); + goto close; + } + + str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + if (str == (char *)MAP_FAILED) { + res = MAIL_ERROR_FETCH; + goto close; + } + + /* strip "From " header for broken implementations */ + /* XXX - called twice, make a function */ + cur_token = 0; + if (size > 5) { + if (strncmp("From ", str, 5) == 0) { + cur_token += 5; + + while (1) { + if (str[cur_token] == '\n') { + cur_token ++; + break; + } + if (cur_token >= size) + break; + cur_token ++; + } + } + } + + mmapstr = mmap_string_new_len(str + cur_token, size - cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto unmap; + } + + if (mmap_string_ref(mmapstr) != 0) { + res = MAIL_ERROR_MEMORY; + goto free_str; + } + + munmap(str, size); + close(fd); + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_str: + mmap_string_free(mmapstr); + unmap: + munmap(str, size); + close: + close(fd); + err: + return res; +} + + +int mhdriver_fetch_header(mailsession * session, uint32_t index, + char ** result, size_t * result_len) +{ + size_t size; + size_t cur_token; + size_t begin; + struct mailmh_folder * folder; + int fd; + MMAPString * mmapstr; + char * str; + int res; + int r; + + folder = get_mh_cur_folder(session); + if (folder == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = mailmh_folder_get_message_fd(folder, index, O_RDONLY, &fd); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + res = mhdriver_mh_error_to_mail_error(r); + goto close; + } + + r = mhdriver_fetch_size(session, index, &size); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + res = mhdriver_mh_error_to_mail_error(r); + goto close; + } + + str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + if (str == (char *)MAP_FAILED) { + res = MAIL_ERROR_FETCH; + goto close; + } + + /* strip "From " header for broken implementations */ + cur_token = 0; + if (size > 5) { + if (strncmp("From ", str, 5) == 0) { + cur_token += 5; + + while (1) { + if (str[cur_token] == '\n') { + cur_token ++; + break; + } + if (cur_token >= size) + break; + cur_token ++; + } + } + } + + begin = cur_token; + + while (1) { + r = mailimf_ignore_field_parse(str, size, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + mailimf_crlf_parse(str, size, &cur_token); + + mmapstr = mmap_string_new_len(str + begin, cur_token - begin); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto unmap; + } + + if (mmap_string_ref(mmapstr) != 0) { + res = MAIL_ERROR_MEMORY; + goto free_str; + } + + munmap(str, size); + close(fd); + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_str: + mmap_string_free(mmapstr); + unmap: + munmap(str, size); + close: + close(fd); + err: + return res; +} + + +int mhdriver_fetch_size(mailsession * session, uint32_t index, + size_t * result) +{ + struct mailmh_folder * folder; + int r; + struct stat buf; + char * name; + + folder = get_mh_cur_folder(session); + if (folder == NULL) + return MAIL_ERROR_FETCH; + + r = mailmh_folder_get_message_filename(folder, index, &name); + + switch (r) { + case MAILMH_NO_ERROR: + break; + + default: + return mhdriver_mh_error_to_mail_error(r); + } + + r = stat(name, &buf); + free(name); + if (r == -1) + return MAIL_ERROR_FETCH; + + * result = buf.st_size; + + return MAIL_NO_ERROR; +} + +int +mhdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + struct mailmh_msg_info * msg_info; + chashdatum key; + chashdatum data; + struct mailmh_folder * folder; + + folder = cached_get_mh_cur_folder(session); +#if 0 + msg_info = cinthash_find(mh_data->cur_folder->fl_msgs_hash, num); + if (msg_info == NULL) + return MAIL_ERROR_CACHE_MISS; +#endif + key.data = # + key.len = sizeof(num); + r = chash_get(folder->fl_msgs_hash, &key, &data); + if (r < 0) + return MAIL_ERROR_CACHE_MISS; + msg_info = data.data; + + snprintf(keyname, PATH_MAX, "%u-%lu-%lu-flags", + num, (unsigned long) msg_info->msg_mtime, + (unsigned long) msg_info->msg_size); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int +mhdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +int mh_get_messages_list(struct mailmh_folder * folder, + mailsession * session, mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + unsigned int i; + struct mailmessage_list * env_list; + int r; + carray * tab; + int res; + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { + struct mailmh_msg_info * mh_info; + mailmessage * msg; + + mh_info = carray_get(folder->fl_msgs_tab, i); + if (mh_info == NULL) + continue; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, driver, + mh_info->msg_index, mh_info->msg_size); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(tab) ; i ++) + mailmessage_free(carray_get(tab, i)); + carray_free(tab); + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_tools.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_tools.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,80 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_tools.h,v 1.10 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef MHDRIVER_TOOLS_H + +#define MHDRIVER_TOOLS_H + +#include "maildriver_types.h" +#include "mail_cache_db_types.h" +#include "mailmh.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mhdriver_mh_error_to_mail_error(int error); + +int mhdriver_fetch_message(mailsession * session, uint32_t index, + char ** result, size_t * result_len); + +int mhdriver_fetch_header(mailsession * session, uint32_t index, + char ** result, size_t * result_len); + +int mhdriver_fetch_size(mailsession * session, uint32_t index, + size_t * result); + +int +mhdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result); + +int +mhdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags); + +int mh_get_messages_list(struct mailmh_folder * folder, + mailsession * session, mailmessage_driver * driver, + struct mailmessage_list ** result); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhdriver_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,100 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhdriver_types.h,v 1.8 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MHDRIVER_TYPES_H + +#define MHDRIVER_TYPES_H + +#include <libetpan/libetpan-config.h> + +#include <libetpan/maildriver_types.h> +#include <libetpan/mailmh.h> +#include <libetpan/clist.h> +#include <libetpan/generic_cache_types.h> +#include <libetpan/mailstorage_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct mh_session_state_data { + struct mailmh * mh_session; + + struct mailmh_folder * mh_cur_folder; + + clist * mh_subscribed_list; +}; + +enum { + MHDRIVER_CACHED_SET_CACHE_DIRECTORY = 1, + MHDRIVER_CACHED_SET_FLAGS_DIRECTORY +}; + +struct mh_cached_session_state_data { + mailsession * mh_ancestor; + char * mh_quoted_mb; + char mh_cache_directory[PATH_MAX]; + char mh_flags_directory[PATH_MAX]; + struct mail_flags_store * mh_flags_store; +}; + +/* mh storage */ + +/* + mh_mailstorage is the state data specific to the MH storage. + + - pathname is the root path of the MH storage. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct mh_mailstorage { + char * mh_pathname; + + int mh_cached; + char * mh_cache_directory; + char * mh_flags_directory; +}; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhstorage.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhstorage.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,204 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhstorage.c,v 1.13 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mhstorage.h" + +#include "mhdriver.h" +#include "mhdriver_cached.h" +#include "mail.h" + +#include <stdlib.h> +#include <string.h> + +/* mh storage */ + +static int mh_mailstorage_connect(struct mailstorage * storage); +static int mh_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void mh_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver mh_mailstorage_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sto_name */ "mh", + /* sto_connect */ mh_mailstorage_connect, + /* sto_get_folder_session */ mh_mailstorage_get_folder_session, + /* sto_uninitialize */ mh_mailstorage_uninitialize, +#else + .sto_name = "mh", + .sto_connect = mh_mailstorage_connect, + .sto_get_folder_session = mh_mailstorage_get_folder_session, + .sto_uninitialize = mh_mailstorage_uninitialize, +#endif +}; + +LIBETPAN_EXPORT +int mh_mailstorage_init(struct mailstorage * storage, + const char * mh_pathname, int mh_cached, + const char * mh_cache_directory, const char * mh_flags_directory) +{ + struct mh_mailstorage * mh_storage; + + mh_storage = malloc(sizeof(* mh_storage)); + if (mh_storage == NULL) + goto err; + + mh_storage->mh_pathname = strdup(mh_pathname); + if (mh_storage->mh_pathname == NULL) + goto free; + + mh_storage->mh_cached = mh_cached; + + if (mh_cached && (mh_cache_directory != NULL) && + (mh_flags_directory != NULL)) { + mh_storage->mh_cache_directory = strdup(mh_cache_directory); + if (mh_storage->mh_cache_directory == NULL) + goto free_pathname; + mh_storage->mh_flags_directory = strdup(mh_flags_directory); + if (mh_storage->mh_flags_directory == NULL) + goto free_cache_directory; + } + else { + mh_storage->mh_cached = FALSE; + mh_storage->mh_cache_directory = NULL; + mh_storage->mh_flags_directory = NULL; + } + + storage->sto_data = mh_storage; + storage->sto_driver = &mh_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(mh_storage->mh_cache_directory); + free_pathname: + free(mh_storage->mh_pathname); + free: + free(mh_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void mh_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct mh_mailstorage * mh_storage; + + mh_storage = storage->sto_data; + if (mh_storage->mh_flags_directory != NULL) + free(mh_storage->mh_flags_directory); + if (mh_storage->mh_cache_directory != NULL) + free(mh_storage->mh_cache_directory); + free(mh_storage->mh_pathname); + free(mh_storage); + + storage->sto_data = NULL; +} + +static int mh_mailstorage_connect(struct mailstorage * storage) +{ + struct mh_mailstorage * mh_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + mh_storage = storage->sto_data; + + if (mh_storage->mh_cached) + driver = mh_cached_session_driver; + else + driver = mh_session_driver; + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (mh_storage->mh_cached) { + r = mailsession_parameters(session, + MHDRIVER_CACHED_SET_CACHE_DIRECTORY, + mh_storage->mh_cache_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + r = mailsession_parameters(session, + MHDRIVER_CACHED_SET_FLAGS_DIRECTORY, + mh_storage->mh_flags_directory); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } + + r = mailsession_connect_path(session, mh_storage->mh_pathname); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int mh_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + int r; + + r = mailsession_select_folder(storage->sto_session, pathname); + if (r != MAIL_NO_ERROR) + return r; + + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhstorage.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mh/mhstorage.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,68 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mhstorage.h,v 1.8 2006/06/02 15:44:29 smarinier Exp $ + */ + +#ifndef MHSTORAGE_H + +#define MHSTORAGE_H + +#include <libetpan/mhdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mh_mailstorage_init is the constructor for a MH storage + + @param pathname is the filename the root path of the MH storage. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache. + + @param flags_directory is the location of the flags. +*/ + +LIBETPAN_EXPORT +int mh_mailstorage_init(struct mailstorage * storage, + const char * mh_pathname, int mh_cached, + const char * mh_cache_directory, const char * mh_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mime-message/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mime-message/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mime-message/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mime-message/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,14 @@ +top_builddir = ../../../.. + +HEADERS = \ + mime_message_driver.h + + +SOURCES = \ + mime_message_driver.c + + +TARGET = libmime-message +INCLUDES = -I../../interface -I$(srcdir)/data-types + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mime-message/mime_message_driver.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mime-message/mime_message_driver.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,946 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mime_message_driver.c,v 1.12 2006/06/26 11:50:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mime_message_driver.h" + +#include "libetpan-config.h" + +#include <sys/stat.h> +#include <sys/types.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif +#include <stdlib.h> +#include <string.h> + +#include "mailmessage.h" +#include "mailmessage_tools.h" +#include "maildriver_tools.h" + +#if 0 +static FILE * get_mime_tmp_file(mailmessage * msg, + char * filename, size_t size) +{ + int fd; + mode_t old_mask; + FILE * f; + + if (msg->msg_data == NULL) + return NULL; + + snprintf(filename, size, "%s/libetpan-mime-XXXXXX", + (char *) msg->msg_data); + + old_mask = umask(0077); + fd = mkstemp(filename); + umask(old_mask); + if (fd == -1) + return NULL; + + f = fdopen(fd, "r+"); + if (f == NULL) { + close(fd); + unlink(filename); + } + + return f; +} +#endif + +int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir) +{ +#if 0 + if (msg->msg_data != NULL) + free(msg->msg_data); + + msg->msg_data = strdup(tmpdir); + if (msg->msg_data == NULL) + return MAIL_ERROR_MEMORY; + +#endif + return MAIL_NO_ERROR; +} + +void mime_message_detach_mime(mailmessage * msg) +{ + msg->msg_mime = NULL; +} + +mailmessage * mime_message_init(struct mailmime * mime) +{ + mailmessage * msg; + int r; + + msg = mailmessage_new(); + if (msg == NULL) + goto err; + + r = mailmessage_init(msg, NULL, mime_message_driver, 0, 0); + if (r != MAIL_NO_ERROR) + goto free; + + if (mime != NULL) { + mailmime_free(msg->msg_mime); + msg->msg_mime = mime; + } + + return msg; + + free: + mailmessage_free(msg); + err: + return NULL; +} + +static int initialize(mailmessage * msg) +{ + struct mailmime * mime; + int res; + + mime = mailmime_new_message_data(NULL); + if (mime == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + msg->msg_mime = mime; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static void uninitialize(mailmessage * msg) +{ + /* tmp dir name */ + if (msg->msg_data != NULL) + free(msg->msg_data); + + if (msg->msg_mime != NULL) + mailmime_free(msg->msg_mime); + msg->msg_mime = NULL; +} + +static void flush(mailmessage * msg) +{ + /* do nothing */ +} + +static void check(mailmessage * msg) +{ + /* do nothing */ +} + +static void fetch_result_free(mailmessage * msg_info, char * content) +{ + mmap_string_unref(content); +} + +#if 0 +static int file_to_mmapstr(FILE * f, + char ** result, size_t * result_len) +{ + int fd; + char * data; + struct stat buf; + MMAPString * mmapstr; + int res; + int r; + + fd = fileno(f); + if (fd == -1) { + res = MAIL_ERROR_FILE; + + goto err; + } + + fflush(f); + r = fstat(fd, &buf); + if (r == -1) { + res = MAIL_ERROR_FILE; + + goto err; + } + + data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (data == (char *)MAP_FAILED) { + res = MAIL_ERROR_FILE; + + goto err; + } + + mmapstr = mmap_string_new_len(data, buf.st_size); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + + goto unmap; + } + + munmap(data, buf.st_size); + + r = mmap_string_ref(mmapstr); + if (r != 0) { + res = MAIL_ERROR_MEMORY; + + goto err; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + unmap: + munmap(data, buf.st_size); + err: + return res; +} +#endif + +#if 0 +static int file_body_to_mmapstr(FILE * f, + char ** result, size_t * result_len) +{ + int fd; + char * data; + struct stat buf; + MMAPString * mmapstr; + size_t cur_token; + int res; + int r; + + fd = fileno(f); + if (fd == -1) { + res = MAIL_ERROR_FILE; + + goto err; + } + + fflush(f); + r = fstat(fd, &buf); + if (r == -1) { + res = MAIL_ERROR_FILE; + + goto err; + } + + data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (data == (char *)MAP_FAILED) { + res = MAIL_ERROR_FILE; + + goto err; + } + + cur_token = 0; + + /* skip header */ + + while (1) { + r = mailimf_ignore_field_parse(data, + buf.st_size, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(data, buf.st_size, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto unmap; + } + + mmapstr = mmap_string_new_len(data + cur_token, buf.st_size - cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + + goto unmap; + } + + munmap(data, buf.st_size); + + r = mmap_string_ref(mmapstr); + if (r != 0) { + res = MAIL_ERROR_MEMORY; + + goto err; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + unmap: + munmap(data, buf.st_size); + err: + return res; +} +#endif + + +static int body_to_mmapstr(char * data, size_t size, + char ** result, size_t * result_len) +{ + MMAPString * mmapstr; + size_t cur_token; + int res; + int r; + + cur_token = 0; + + /* skip header */ + + while (1) { + r = mailimf_ignore_field_parse(data, size, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(data, size, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto err; + } + + mmapstr = mmap_string_new_len(data + cur_token, size - cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r != 0) { + mmap_string_free(mmapstr); + res = MAIL_ERROR_MEMORY; + + goto err; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + err: + return res; +} + + +#if 0 +static int file_body_body_to_mmapstr(FILE * f, + char ** result, size_t * result_len) +{ + int fd; + char * data; + struct stat buf; + MMAPString * mmapstr; + size_t cur_token; + int res; + int r; + + fd = fileno(f); + if (fd == -1) { + res = MAIL_ERROR_FILE; + + goto err; + } + + fflush(f); + r = fstat(fd, &buf); + if (r == -1) { + res = MAIL_ERROR_FILE; + + goto err; + } + + data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (data == (char *)MAP_FAILED) { + res = MAIL_ERROR_FILE; + + goto err; + } + + cur_token = 0; + + /* skip header */ + + /* MIME header */ + + while (1) { + r = mailimf_ignore_field_parse(data, + buf.st_size, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(data, buf.st_size, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto unmap; + } + + /* headers */ + + while (1) { + r = mailimf_ignore_field_parse(data, + buf.st_size, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(data, buf.st_size, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto unmap; + } + + mmapstr = mmap_string_new_len(data + cur_token, buf.st_size - cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + + goto unmap; + } + + munmap(data, buf.st_size); + + r = mmap_string_ref(mmapstr); + if (r != 0) { + res = MAIL_ERROR_MEMORY; + + goto err; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + unmap: + munmap(data, buf.st_size); + err: + return res; +} +#endif + +static int body_body_to_mmapstr(char * data, size_t size, + char ** result, size_t * result_len) +{ + size_t cur_token; + int res; + int r; + + cur_token = 0; + + /* skip header */ + + /* MIME header */ + + while (1) { + r = mailimf_ignore_field_parse(data, size, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(data, size, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto err; + } + + return body_to_mmapstr(data + cur_token, size - cur_token, + result, result_len); + + err: + return res; +} + + +static int fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + int r; +#if 0 + FILE * f; +#endif + int res; + int col; +#if 0 + char filename[PATH_MAX]; +#endif + MMAPString * str; + + if (msg_info->msg_mime == NULL) + return MAIL_ERROR_INVAL; + +#if 0 + f = get_mime_tmp_file(msg_info, filename, sizeof(filename)); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } +#endif + + str = mmap_string_new(""); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + col = 0; + r = mailmime_write_mem(str, &col, mime); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto free; + } + +#if 0 + if (mime->mm_parent == NULL) + r = file_to_mmapstr(f, result, result_len); + else + r = file_body_to_mmapstr(f, result, result_len); +#endif + if (mime->mm_parent == NULL) { + r = mmap_string_ref(str); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + * result = str->str; + * result_len = str->len; + + r = MAIL_NO_ERROR; + } + else { + r = body_to_mmapstr(str->str, str->len, result, result_len); + if (r == MAIL_NO_ERROR) { + mmap_string_free(str); + } + } + + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + +#if 0 + fclose(f); + unlink(filename); +#endif + + return MAIL_NO_ERROR; + + free: +#if 0 + fclose(f); + unlink(filename); +#endif + mmap_string_free(str); + err: + return res; +} + + +static int fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + int r; +#if 0 + FILE * f; +#endif + int res; + int col; +#if 0 + char filename[PATH_MAX]; +#endif + MMAPString * str; + + if (msg_info->msg_mime == NULL) + return MAIL_ERROR_INVAL; + +#if 0 + f = get_mime_tmp_file(msg_info, filename, sizeof(filename)); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } +#endif + + str = mmap_string_new(""); + if (str == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + col = 0; + if (mime->mm_type == MAILMIME_MESSAGE) { + if (mime->mm_data.mm_message.mm_fields != NULL) { +#if 0 + r = mailimf_fields_write(f, &col, mime->mm_data.mm_message.mm_fields); +#endif + r = mailimf_fields_write_mem(str, &col, mime->mm_data.mm_message.mm_fields); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto free; + } +#if 0 + mailimf_string_write(f, &col, "\r\n", 2); +#endif + mailimf_string_write_mem(str, &col, "\r\n", 2); + } + } + + r = mmap_string_ref(str); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + +#if 0 + r = file_to_mmapstr(f, result, result_len); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } +#endif + * result = str->str; + * result_len = str->len; + +#if 0 + fclose(f); + unlink(filename); +#endif + + return MAIL_NO_ERROR; + +#if 0 + close: + fclose(f); + unlink(filename); +#endif + free: + mmap_string_free(str); + err: + return res; +} + + +static int fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + int r; +#if 0 + FILE * f; +#endif + int res; + int col; +#if 0 + char filename[PATH_MAX]; +#endif + MMAPString * str; + + if (msg_info->msg_mime == NULL) + return MAIL_ERROR_INVAL; + + str = mmap_string_new(""); + if (str == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + +#if 0 + f = get_mime_tmp_file(msg_info, filename, sizeof(filename)); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } +#endif + + col = 0; + if (mime->mm_content_type != NULL) { +#if 0 + r = mailmime_content_write(f, &col, mime->mm_content_type); +#endif + r = mailmime_content_write_mem(str, &col, mime->mm_content_type); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto free; + } + } + if (mime->mm_mime_fields != NULL) { + r = mailmime_fields_write_mem(str, &col, mime->mm_mime_fields); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto free; + } + } + mailimf_string_write_mem(str, &col, "\r\n", 2); + +#if 0 + r = file_to_mmapstr(f, result, result_len); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + fclose(f); + unlink(filename); +#endif + + r = mmap_string_ref(str); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + * result = str->str; + * result_len = str->len; + + return MAIL_NO_ERROR; + +#if 0 + close: + fclose(f); + unlink(filename); +#endif + free: + mmap_string_free(str); + err: + return res; +} + + + +static int fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + int r; +#if 0 + FILE * f; +#endif + int res; + int col; +#if 0 + char filename[PATH_MAX]; +#endif + MMAPString * str; + + if (msg_info->msg_mime == NULL) + return MAIL_ERROR_INVAL; + + str = mmap_string_new(""); + if (str == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + +#if 0 + f = get_mime_tmp_file(msg_info, filename, sizeof(filename)); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } +#endif + + col = 0; + if (mime->mm_mime_fields != NULL) { +#if 0 + r = mailmime_write(f, &col, mime); +#endif + r = mailmime_write_mem(str, &col, mime); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto free; + } + } + + if (mime->mm_type == MAILMIME_MESSAGE) + r = body_body_to_mmapstr(str->str, str->len, result, result_len); + else + r = body_to_mmapstr(str->str, str->len, result, result_len); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + mmap_string_free(str); + +#if 0 + fclose(f); + unlink(filename); +#endif + + return MAIL_NO_ERROR; + +#if 0 + close: + fclose(f); + unlink(filename); +#endif + free: + mmap_string_free(str); + err: + return res; +} + + +static int get_bodystructure(mailmessage * msg_info, + struct mailmime ** result) +{ + if (msg_info->msg_mime == NULL) + return MAIL_ERROR_INVAL; + + * result = msg_info->msg_mime; + + return MAIL_NO_ERROR; +} + + +static int fetch(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + return fetch_section(msg_info, msg_info->msg_mime, result, result_len); +} + +static int fetch_header(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + return fetch_section_header(msg_info, + msg_info->msg_mime, result, result_len); +} + +static int fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + return fetch_section_body(msg_info, msg_info->msg_mime, result, result_len); +} + + +static int fetch_size(mailmessage * msg_info, + size_t * result) +{ + char * msg; + int r; + + r = fetch(msg_info, &msg, result); + if (r != MAIL_NO_ERROR) { + return r; + } + + fetch_result_free(msg_info, msg); + + return MAIL_NO_ERROR; +} + + +static mailmessage_driver local_mime_message_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* msg_name */ "mime", + + /* msg_initialize */ initialize, + /* msg_uninitialize */ uninitialize, + + /* msg_flush */ flush, + /* msg_check */ check, + + /* msg_fetch_result_free */ fetch_result_free, + + /* msg_fetch */ fetch, + /* msg_fetch_header */ fetch_header, + /* msg_fetch_body */ fetch_body, + /* msg_fetch_size */ fetch_size, + /* msg_get_bodystructure */ get_bodystructure, + /* msg_fetch_section */ fetch_section, + /* msg_fetch_section_header */ fetch_section_header, + /* msg_fetch_section_mime */ fetch_section_mime, + /* msg_fetch_section_body */ fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ NULL, +#else + .msg_name = "mime", + + .msg_initialize = initialize, + .msg_uninitialize = uninitialize, + + .msg_flush = flush, + .msg_check = check, + + .msg_fetch_result_free = fetch_result_free, + + .msg_fetch = fetch, + .msg_fetch_header = fetch_header, + .msg_fetch_body = fetch_body, + .msg_fetch_size = fetch_size, + .msg_get_bodystructure = get_bodystructure, + .msg_fetch_section = fetch_section, + .msg_fetch_section_header = fetch_section_header, + .msg_fetch_section_mime = fetch_section_mime, + .msg_fetch_section_body = fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = NULL, +#endif +}; + +mailmessage_driver * mime_message_driver = &local_mime_message_driver; Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/mime-message/mime_message_driver.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/mime-message/mime_message_driver.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,53 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mime_message_driver.h,v 1.5 2004/12/13 23:18:28 hoa Exp $ + */ + +#ifndef MIME_MESSAGE_DRIVER_H + +#define MIME_MESSAGE_DRIVER_H + +#include <libetpan/mailmessage.h> + +#define LIBETPAN_MIME_MESSAGE + +extern mailmessage_driver * mime_message_driver; + +mailmessage * mime_message_init(struct mailmime * mime); + +void mime_message_detach_mime(mailmessage * msg); + +/* deprecated */ +int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir); + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,30 @@ +top_builddir = ../../../.. + +HEADERS = \ + nntpdriver.h \ + nntpdriver_cached.h \ + nntpdriver_cached_message.h \ + nntpdriver_message.h \ + nntpdriver_types.h \ + nntpstorage.h + + +SOURCES = \ + nntpdriver.c \ + nntpdriver_cached.c \ + nntpdriver_cached_message.c \ + nntpdriver_message.c \ + nntpdriver_tools.c \ + nntpstorage.c + + +TARGET = libnntp +INCLUDES = -I../../interface \ + -I../../tools \ + -I$(srcdir)/low-level/nntp \ + -I$(srcdir)/low-level/mime \ + -I$(srcdir)/low-level/imf \ + -I$(srcdir)/data-types + + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1236 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver.c,v 1.51 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "nntpdriver.h" + +#include <string.h> +#include <stdlib.h> + +#include "mail.h" +#include "mailmessage.h" +#include "nntpdriver_tools.h" +#include "maildriver_tools.h" +#include "nntpdriver_message.h" + +static int nntpdriver_initialize(mailsession * session); + +static void nntpdriver_uninitialize(mailsession * session); + +static int nntpdriver_parameters(mailsession * session, + int id, void * value); + +static int nntpdriver_connect_stream(mailsession * session, mailstream * s); + +static int nntpdriver_login(mailsession * session, + const char * userid, const char * password); + +static int nntpdriver_logout(mailsession * session); + +static int nntpdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen); + +static int nntpdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int nntpdriver_append_message(mailsession * session, + const char * message, size_t size); + +static int nntpdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +static int +nntpdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + + +static int nntpdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int nntpdriver_list_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int nntpdriver_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int nntpdriver_subscribe_folder(mailsession * session, const char * mb); + +static int nntpdriver_unsubscribe_folder(mailsession * session, const char * mb); + +static int nntpdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int nntpdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static int nntpdriver_noop(mailsession * session); + +static mailsession_driver local_nntp_session_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sess_name */ "nntp", + + /* sess_initialize */ nntpdriver_initialize, + /* sess_uninitialize */ nntpdriver_uninitialize, + + /* sess_parameters */ nntpdriver_parameters, + + /* sess_connect_stream */ nntpdriver_connect_stream, + /* sess_connect_path */ NULL, + /* sess_starttls */ NULL, + /* sess_login */ nntpdriver_login, + /* sess_logout */ nntpdriver_logout, + /* sess_noop */ nntpdriver_noop, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ NULL, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ nntpdriver_select_folder, + /* sess_expunge_folder */ NULL, + /* sess_status_folder */ nntpdriver_status_folder, + /* sess_messages_number */ nntpdriver_messages_number, + /* sess_recent_number */ nntpdriver_messages_number, + /* sess_unseen_number */ nntpdriver_messages_number, + /* sess_list_folders */ nntpdriver_list_folders, + /* sess_lsub_folders */ nntpdriver_lsub_folders, + /* sess_subscribe_folder */ nntpdriver_subscribe_folder, + /* sess_unsubscribe_folder */ nntpdriver_unsubscribe_folder, + + /* sess_append_message */ nntpdriver_append_message, + /* sess_append_message_flags */ nntpdriver_append_message_flags, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ nntpdriver_get_message, + /* sess_get_message_by_uid */ nntpdriver_get_message_by_uid, + + /* sess_get_messages_list */ nntpdriver_get_messages_list, + /* sess_get_envelopes_list */ nntpdriver_get_envelopes_list, + /* sess_remove_message */ NULL, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL, + +#else + .sess_name = "nntp", + + .sess_initialize = nntpdriver_initialize, + .sess_uninitialize = nntpdriver_uninitialize, + + .sess_parameters = nntpdriver_parameters, + + .sess_connect_stream = nntpdriver_connect_stream, + .sess_connect_path = NULL, + .sess_starttls = NULL, + .sess_login = nntpdriver_login, + .sess_logout = nntpdriver_logout, + .sess_noop = nntpdriver_noop, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = NULL, + .sess_examine_folder = NULL, + .sess_select_folder = nntpdriver_select_folder, + .sess_expunge_folder = NULL, + .sess_status_folder = nntpdriver_status_folder, + .sess_messages_number = nntpdriver_messages_number, + .sess_recent_number = nntpdriver_messages_number, + .sess_unseen_number = nntpdriver_messages_number, + .sess_list_folders = nntpdriver_list_folders, + .sess_lsub_folders = nntpdriver_lsub_folders, + .sess_subscribe_folder = nntpdriver_subscribe_folder, + .sess_unsubscribe_folder = nntpdriver_unsubscribe_folder, + + .sess_append_message = nntpdriver_append_message, + .sess_append_message_flags = nntpdriver_append_message_flags, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = nntpdriver_get_messages_list, + .sess_get_envelopes_list = nntpdriver_get_envelopes_list, + .sess_remove_message = NULL, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = nntpdriver_get_message, + .sess_get_message_by_uid = nntpdriver_get_message_by_uid, + .sess_login_sasl = NULL, +#endif +}; + + +mailsession_driver * nntp_session_driver = &local_nntp_session_driver; + +static inline struct nntp_session_state_data * +get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline newsnntp * get_nntp_session(mailsession * session) +{ + return get_data(session)->nntp_session; +} + +static int nntpdriver_initialize(mailsession * session) +{ + struct nntp_session_state_data * data; + newsnntp * nntp; + + nntp = newsnntp_new(0, NULL); + if (nntp == NULL) + goto err; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto free; + + data->nntp_session = nntp; + + data->nntp_userid = NULL; + data->nntp_password = NULL; + + data->nntp_group_info = NULL; + data->nntp_group_name = NULL; + + data->nntp_subscribed_list = clist_new(); + if (data->nntp_subscribed_list == NULL) + goto free_data; + + data->nntp_max_articles = 0; + + data->nntp_mode_reader = FALSE; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_data: + free(data); + free: + newsnntp_free(nntp); + err: + return MAIL_ERROR_MEMORY; +} + +static void nntpdriver_uninitialize(mailsession * session) +{ + struct nntp_session_state_data * data; + + data = get_data(session); + + clist_foreach(data->nntp_subscribed_list, (clist_func) free, NULL); + clist_free(data->nntp_subscribed_list); + + if (data->nntp_group_info != NULL) + newsnntp_group_free(data->nntp_group_info); + + if (data->nntp_group_name != NULL) + free(data->nntp_group_name); + + if (data->nntp_userid != NULL) + free(data->nntp_userid); + + if (data->nntp_password != NULL) + free(data->nntp_password); + + newsnntp_free(data->nntp_session); + free(data); + + session->sess_data = NULL; +} + + +static int nntpdriver_parameters(mailsession * session, + int id, void * value) +{ + struct nntp_session_state_data * data; + + data = get_data(session); + + switch (id) { + case NNTPDRIVER_SET_MAX_ARTICLES: + { + uint32_t * param; + + param = value; + + data->nntp_max_articles = * param; + return MAIL_NO_ERROR; + } + } + + return MAIL_ERROR_INVAL; +} + + +static int add_to_list(mailsession * session, const char * mb) +{ + char * new_mb; + int r; + struct nntp_session_state_data * data; + + data = get_data(session); + + new_mb = strdup(mb); + if (new_mb == NULL) + return -1; + + r = clist_append(data->nntp_subscribed_list, new_mb); + if (r < 0) { + free(new_mb); + return -1; + } + + return 0; +} + +static int remove_from_list(mailsession * session, const char * mb) +{ + clistiter * cur; + struct nntp_session_state_data * data; + + data = get_data(session); + + for(cur = clist_begin(data->nntp_subscribed_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * cur_name; + + cur_name = clist_content(cur); + if (strcmp(cur_name, mb) == 0) { + clist_delete(data->nntp_subscribed_list, cur); + free(cur_name); + return 0; + } + } + + return -1; +} + + +static int nntpdriver_connect_stream(mailsession * session, mailstream * s) +{ + int r; + + r = newsnntp_connect(get_nntp_session(session), s); + + switch (r) { + case NEWSNNTP_NO_ERROR: + return MAIL_NO_ERROR_NON_AUTHENTICATED; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } +} + +static int nntpdriver_login(mailsession * session, + const char * userid, const char * password) +{ + struct nntp_session_state_data * data; + char * new_userid; + char * new_password; + + data = get_data(session); + + if (userid != NULL) { + new_userid = strdup(userid); + if (new_userid == NULL) + goto err; + } + else + new_userid = NULL; + + if (password != NULL) { + new_password = strdup(password); + if (new_password == NULL) + goto free_uid; + } + else + new_password = NULL; + + data->nntp_userid = new_userid; + data->nntp_password = new_password; + + return MAIL_NO_ERROR; + + free_uid: + if (new_userid != NULL) + free(new_userid); + err: + return MAIL_ERROR_MEMORY; +} + +static int nntpdriver_logout(mailsession * session) +{ + int r; + + r = newsnntp_quit(get_nntp_session(session)); + + return nntpdriver_nntp_error_to_mail_error(r); +} + + +static int nntpdriver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen) +{ + uint32_t count; + int r; + + r = nntpdriver_select_folder(session, mb); + if (r != MAIL_NO_ERROR) + return r; + + r = nntpdriver_messages_number(session, mb, &count); + if (r != MAIL_NO_ERROR) + return r; + + * result_messages = count; + * result_recent = count; + * result_unseen = count; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + int r; + struct nntp_session_state_data * data; + + if (mb != NULL) { + r = nntpdriver_select_folder(session, mb); + if (r != MAIL_NO_ERROR) + return r; + } + + data = get_data(session); + + if (data->nntp_group_info == NULL) + return MAIL_ERROR_FOLDER_NOT_FOUND; + + * result = data->nntp_group_info->grp_last - + data->nntp_group_info->grp_first + 1; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_list_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + int r; + clist * group_list; + newsnntp * nntp; + clistiter * cur; + char * new_mb; + int done; + clist * list; + struct mail_list * ml; + int res; + + nntp = get_nntp_session(session); + + new_mb = NULL; + if ((mb != NULL) && (*mb != '\0')) { + new_mb = malloc(strlen(mb) + 3); + if (new_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + strcpy(new_mb, mb); + strcat(new_mb, ".*"); + } + + done = FALSE; + do { + if (new_mb != NULL) + r = newsnntp_list_active(nntp, new_mb, &group_list); + else + r = newsnntp_list(nntp, &group_list); + + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + break; + + case NEWSNNTP_NO_ERROR: + if (new_mb != NULL) + free(new_mb); + done = TRUE; + break; + + default: + if (new_mb != NULL) + free(new_mb); + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (!done); + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(group_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct newsnntp_group_info * info; + char * new_name; + + info = clist_content(cur); + new_name = strdup(info->grp_name); + if (new_name == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, new_name); + if (r < 0) { + free(new_name); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + ml = mail_list_new(list); + if (ml == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + newsnntp_list_free(group_list); + + * result = ml; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + newsnntp_list_free(group_list); + err: + return res; +} + +static int nntpdriver_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + clist * subscribed; + clist * lsub_result; + clistiter * cur; + struct mail_list * lsub; + size_t length; + int res; + int r; + struct nntp_session_state_data * data; + + length = strlen(mb); + + data = get_data(session); + + subscribed = data->nntp_subscribed_list; + lsub_result = clist_new(); + if (lsub_result == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(subscribed) ; cur != NULL ; + cur = clist_next(cur)) { + char * cur_mb; + char * new_mb; + + cur_mb = clist_content(cur); + + if (strncmp(mb, cur_mb, length) == 0) { + new_mb = strdup(cur_mb); + if (new_mb == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(lsub_result, new_mb); + if (r < 0) { + free(new_mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + lsub = mail_list_new(lsub_result); + if (lsub == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = lsub; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(lsub_result, (clist_func) free, NULL); + clist_free(lsub_result); + err: + return res; +} + +static int nntpdriver_subscribe_folder(mailsession * session, const char * mb) +{ + int r; + + r = add_to_list(session, mb); + if (r < 0) + return MAIL_ERROR_SUBSCRIBE; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_unsubscribe_folder(mailsession * session, const char * mb) +{ + int r; + + r = remove_from_list(session, mb); + if (r < 0) + return MAIL_ERROR_UNSUBSCRIBE; + + return MAIL_NO_ERROR; +} + + + +/* messages operations */ + +static int nntpdriver_append_message(mailsession * session, + const char * message, size_t size) +{ + int r; + struct nntp_session_state_data * data; + + data = get_data(session); + + do { + r = newsnntp_post(get_nntp_session(session), message, size); + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (1); +} + +static int nntpdriver_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + return nntpdriver_append_message(session, message, size); +} + + +static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, + struct mailimf_fields ** result); + + +static int +nntpdriver_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + newsnntp * nntp; + int r; + struct nntp_session_state_data * data; + clist * list; + int done; + clistiter * cur; + uint32_t first_seq; + unsigned int i; + + nntp = get_nntp_session(session); + + data = get_data(session); + + if (data->nntp_group_info == NULL) + return MAIL_ERROR_BAD_STATE; + + first_seq = data->nntp_group_info->grp_first; + + if (carray_count(env_list->msg_tab) > 0) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, 0); + + first_seq = msg->msg_index; + } + + if (carray_count(env_list->msg_tab) > 0) { + i = carray_count(env_list->msg_tab) - 1; + while (1) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + first_seq = msg->msg_index + 1; + break; + } + + if (i == 0) + break; + + i --; + } + } + + if (first_seq > data->nntp_group_info->grp_last) { + list = NULL; + } + else { + done = FALSE; + do { + r = newsnntp_xover_range(nntp, first_seq, + data->nntp_group_info->grp_last, &list); + + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (!done); + } + +#if 0 + i = 0; + j = 0; + + if (list != NULL) { + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + struct newsnntp_xover_resp_item * item; + struct mailimf_fields * fields; + + item = clist_content(cur); + + while (i < carray_count(env_list->msg_tab)) { + mailmessage * info; + + info = carray_get(env_list->msg_tab, i); + + if (item->ovr_article == info->msg_index) { + + if (info->fields == NULL) { + r = xover_resp_to_fields(item, &fields); + if (r == MAIL_NO_ERROR) { + info->fields = fields; + } + + info->size = item->ovr_size; + + carray_set(env_list->msg_tab, j, info); + j ++; + i ++; + break; + } + else { + carray_set(env_list->msg_tab, j, info); + j ++; + } + } + else { + if (info->fields != NULL) { + carray_set(env_list->msg_tab, j, info); + j ++; + } + else { + if (info->flags != NULL) { + info->flags->flags &= ~MAIL_FLAG_NEW; + info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED; + mailmessage_check(info); + } + mailmessage_free(info); + carray_set(env_list->msg_tab, i, NULL); + } + } + + i ++; + } + } + } + + while (i < carray_count(env_list->msg_tab)) { + mailmessage * info; + + info = carray_get(env_list->msg_tab, i); + if (info->fields != NULL) { + carray_set(env_list->msg_tab, j, info); + j ++; + } + else { + if (info->flags != NULL) { + info->flags->flags &= ~MAIL_FLAG_NEW; + info->flags->flags |= MAIL_FLAG_SEEN | MAIL_FLAG_DELETED; + mailmessage_check(info); + } + mailmessage_free(info); + carray_set(env_list->msg_tab, i, NULL); + } + + i ++; + } + + r = carray_set_size(env_list->msg_tab, j); + if (r < 0) { + if (list != NULL) + newsnntp_xover_resp_list_free(list); + return MAIL_ERROR_MEMORY; + } +#endif + i = 0; + + if (list != NULL) { + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + struct newsnntp_xover_resp_item * item; + struct mailimf_fields * fields; + + item = clist_content(cur); + + while (i < carray_count(env_list->msg_tab)) { + mailmessage * info; + + info = carray_get(env_list->msg_tab, i); + + if (item->ovr_article == info->msg_index) { + + if (info->msg_fields == NULL) { + fields = NULL; + r = xover_resp_to_fields(item, &fields); + if (r == MAIL_NO_ERROR) { + info->msg_fields = fields; + } + + info->msg_size = item->ovr_size; + + i ++; + break; + } + } +#if 0 + else if ((info->fields == NULL) && (info->flags != NULL)) { + info->flags->flags &= ~MAIL_FLAG_NEW; + info->flags->flags |= MAIL_FLAG_CANCELLED; + mailmessage_check(info); + } +#endif + + i ++; + } + } + } + +#if 0 + while (i < env_list->msg_tab->len) { + mailmessage * info; + + info = carray_get(env_list->msg_tab, i); + if ((info->fields == NULL) && (info->flags != NULL)) { + info->flags->flags &= ~MAIL_FLAG_NEW; + info->flags->flags |= MAIL_FLAG_CANCELLED; + mailmessage_check(info); + } + + i ++; + } +#endif + + if (list != NULL) + newsnntp_xover_resp_list_free(list); + + return MAIL_NO_ERROR; +} + + +static int xover_resp_to_fields(struct newsnntp_xover_resp_item * item, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + int r; + struct mailimf_fields * fields; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + if (item->ovr_subject != NULL) { + char * subject_str; + struct mailimf_subject * subject; + struct mailimf_field * field; + + subject_str = strdup(item->ovr_subject); + if (subject_str == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + subject = mailimf_subject_new(subject_str); + if (subject == NULL) { + free(subject_str); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_SUBJECT, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, subject, NULL, NULL, NULL); + if (field == NULL) { + mailimf_subject_free(subject); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (item->ovr_author != NULL) { + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + struct mailimf_field * field; + + cur_token = 0; + r = mailimf_mailbox_list_parse(item->ovr_author, strlen(item->ovr_author), + &cur_token, &mb_list); + switch (r) { + case MAILIMF_NO_ERROR: + from = mailimf_from_new(mb_list); + if (from == NULL) { + mailimf_mailbox_list_free(mb_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, from, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_from_free(from); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + if (item->ovr_date != NULL) { + struct mailimf_date_time * date_time; + struct mailimf_orig_date * orig_date; + struct mailimf_field * field; + + cur_token = 0; + r = mailimf_date_time_parse(item->ovr_date, strlen(item->ovr_date), + &cur_token, &date_time); + switch (r) { + case MAILIMF_NO_ERROR: + orig_date = mailimf_orig_date_new(date_time); + if (orig_date == NULL) { + mailimf_date_time_free(date_time); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, orig_date, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL); + if (field == NULL) { + mailimf_orig_date_free(orig_date); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + if (item->ovr_message_id != NULL) { + char * msgid_str; + struct mailimf_message_id * msgid; + struct mailimf_field * field; + + cur_token = 0; + r = mailimf_msg_id_parse(item->ovr_message_id, strlen(item->ovr_message_id), + &cur_token, &msgid_str); + + switch (r) { + case MAILIMF_NO_ERROR: + msgid = mailimf_message_id_new(msgid_str); + if (msgid == NULL) { + mailimf_msg_id_free(msgid_str); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, msgid, NULL, + NULL, NULL, NULL, NULL, NULL); + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + break; + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + if (item->ovr_references != NULL) { + clist * msgid_list; + struct mailimf_references * references; + struct mailimf_field * field; + + cur_token = 0; + + r = mailimf_msg_id_list_parse(item->ovr_references, strlen(item->ovr_references), + &cur_token, &msgid_list); + + switch (r) { + case MAILIMF_NO_ERROR: + references = mailimf_references_new(msgid_list); + if (references == NULL) { + clist_foreach(msgid_list, + (clist_func) mailimf_msg_id_free, NULL); + clist_free(msgid_list); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + field = mailimf_field_new(MAILIMF_FIELD_REFERENCES, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + references, NULL, NULL, NULL, NULL); + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + case MAILIMF_ERROR_PARSE: + break; + + default: + res = maildriver_imf_error_to_mail_error(r); + goto free_list; + } + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = fields; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + err: + return res; +} + + +/* get messages list with group info */ + +static int nntpdriver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + return nntp_get_messages_list(session, session, nntp_message_driver, result); + +} + +static int nntpdriver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, nntp_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_noop(mailsession * session) +{ + newsnntp * nntp; + int r; + struct tm tm; + + nntp = get_nntp_session(session); + + r = newsnntp_date(nntp, &tm); + + return nntpdriver_nntp_error_to_mail_error(r); +} + +static int nntpdriver_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t num; + char * p; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = strtoul(uid, &p, 10); + if ((p == uid) || (* p != '\0')) + return MAIL_ERROR_INVAL; + + return nntpdriver_get_message(session, num, result); + } Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver.h,v 1.16 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef NNTPDRIVER_H + +#define NNTPDRIVER_H + +#include <libetpan/nntpdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * nntp_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_cached.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_cached.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1119 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_cached.c,v 1.53 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "nntpdriver_cached.h" + +#include "libetpan-config.h" + +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <stdlib.h> +#ifdef _MSC_VER +# include "win_etpan.h" +#endif + +#include "mail_cache_db.h" + +#include "mail.h" +#include "mailmessage.h" +#include "maildriver_tools.h" +#include "nntpdriver.h" +#include "maildriver.h" +#include "newsnntp.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "maillock.h" +#include "nntpdriver_cached_message.h" +#include "nntpdriver_tools.h" + +static int nntpdriver_cached_initialize(mailsession * session); + +static void nntpdriver_cached_uninitialize(mailsession * session); + +static int nntpdriver_cached_parameters(mailsession * session, + int id, void * value); + +static int nntpdriver_cached_connect_stream(mailsession * session, + mailstream * s); + +static int nntpdriver_cached_login(mailsession * session, + const char * userid, const char * password); + +static int nntpdriver_cached_logout(mailsession * session); + +static int nntpdriver_cached_check_folder(mailsession * session); + +static int nntpdriver_cached_select_folder(mailsession * session, const char * mb); + +static int nntpdriver_cached_status_folder(mailsession * session, + const char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen); + +static int nntpdriver_cached_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int nntpdriver_cached_recent_number(mailsession * session, const char * mb, + uint32_t * result); + +static int nntpdriver_cached_unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +static int nntpdriver_cached_append_message(mailsession * session, + const char * message, size_t size); + +static int nntpdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +static int +nntpdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + + +static int +nntpdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int nntpdriver_cached_list_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int nntpdriver_cached_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +static int nntpdriver_cached_subscribe_folder(mailsession * session, + const char * mb); + +static int nntpdriver_cached_unsubscribe_folder(mailsession * session, + const char * mb); + +static int nntpdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int nntpdriver_cached_noop(mailsession * session); + +static int nntpdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result); + +static mailsession_driver local_nntp_cached_session_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sess_name */ "nntp-cached", + + /* sess_initialize */ nntpdriver_cached_initialize, + /* sess_uninitialize */ nntpdriver_cached_uninitialize, + + /* sess_parameters */ nntpdriver_cached_parameters, + + /* sess_connect_stream */ nntpdriver_cached_connect_stream, + /* sess_connect_path */ NULL, + /* sess_starttls */ NULL, + /* sess_login */ nntpdriver_cached_login, + /* sess_logout */ nntpdriver_cached_logout, + /* sess_noop */ nntpdriver_cached_noop, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ nntpdriver_cached_check_folder, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ nntpdriver_cached_select_folder, + /* sess_expunge_folder */ NULL, + /* sess_status_folder */ nntpdriver_cached_status_folder, + /* sess_messages_number */ nntpdriver_cached_messages_number, + /* sess_recent_number */ nntpdriver_cached_recent_number, + /* sess_unseen_number */ nntpdriver_cached_unseen_number, + /* sess_list_folders */ nntpdriver_cached_list_folders, + /* sess_lsub_folders */ nntpdriver_cached_lsub_folders, + /* sess_subscribe_folder */ nntpdriver_cached_subscribe_folder, + /* sess_unsubscribe_folder */ nntpdriver_cached_unsubscribe_folder, + + /* sess_append_message */ nntpdriver_cached_append_message, + /* sess_append_message_flags */ nntpdriver_cached_append_message_flags, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ nntpdriver_cached_get_message, + /* sess_get_message_by_uid */ nntpdriver_cached_get_message_by_uid, + + /* sess_get_messages_list */ nntpdriver_cached_get_messages_list, + /* sess_get_envelopes_list */ nntpdriver_cached_get_envelopes_list, + /* sess_remove_message */ NULL, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ NULL, + +#else + .sess_name = "nntp-cached", + + .sess_initialize = nntpdriver_cached_initialize, + .sess_uninitialize = nntpdriver_cached_uninitialize, + + .sess_parameters = nntpdriver_cached_parameters, + + .sess_connect_stream = nntpdriver_cached_connect_stream, + .sess_connect_path = NULL, + .sess_starttls = NULL, + .sess_login = nntpdriver_cached_login, + .sess_logout = nntpdriver_cached_logout, + .sess_noop = nntpdriver_cached_noop, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = nntpdriver_cached_check_folder, + .sess_examine_folder = NULL, + .sess_select_folder = nntpdriver_cached_select_folder, + .sess_expunge_folder = NULL, + .sess_status_folder = nntpdriver_cached_status_folder, + .sess_messages_number = nntpdriver_cached_messages_number, + .sess_recent_number = nntpdriver_cached_recent_number, + .sess_unseen_number = nntpdriver_cached_unseen_number, + .sess_list_folders = nntpdriver_cached_list_folders, + .sess_lsub_folders = nntpdriver_cached_lsub_folders, + .sess_subscribe_folder = nntpdriver_cached_subscribe_folder, + .sess_unsubscribe_folder = nntpdriver_cached_unsubscribe_folder, + + .sess_append_message = nntpdriver_cached_append_message, + .sess_append_message_flags = nntpdriver_cached_append_message_flags, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = nntpdriver_cached_get_messages_list, + .sess_get_envelopes_list = nntpdriver_cached_get_envelopes_list, + .sess_remove_message = NULL, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = nntpdriver_cached_get_message, + .sess_get_message_by_uid = nntpdriver_cached_get_message_by_uid, + .sess_login_sasl = NULL, +#endif +}; + + +mailsession_driver * nntp_cached_session_driver = +&local_nntp_cached_session_driver; + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + + + +static void read_article_seq(mailsession * session, + uint32_t * pfirst, uint32_t * plast); + +static void write_article_seq(mailsession * session, + uint32_t first, uint32_t last); + + +static inline struct nntp_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->nntp_ancestor; +} + +static inline struct nntp_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + +static inline newsnntp * get_nntp_session(mailsession * session) +{ + return get_ancestor_data(session)->nntp_session; +} + +static int nntpdriver_cached_initialize(mailsession * session) +{ + struct nntp_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->nntp_flags_store = mail_flags_store_new(); + if (data->nntp_flags_store == NULL) + goto free; + + data->nntp_ancestor = mailsession_new(nntp_session_driver); + if (data->nntp_ancestor == NULL) + goto free_store; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_store: + mail_flags_store_free(data->nntp_flags_store); + free: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static int nntp_flags_store_process(char * flags_directory, char * group_name, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + if (group_name == NULL) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + flags_directory, group_name, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_index, msg->msg_flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void nntpdriver_cached_uninitialize(mailsession * session) +{ + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + mail_flags_store_free(cached_data->nntp_flags_store); + + mailsession_free(cached_data->nntp_ancestor); + free(cached_data); + + session->sess_data = NULL; +} + +static int nntpdriver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct nntp_cached_session_state_data * cached_data; + int r; + + cached_data = get_cached_data(session); + + switch (id) { + case NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(cached_data->nntp_cache_directory, value, PATH_MAX); + cached_data->nntp_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(cached_data->nntp_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(cached_data->nntp_flags_directory, value, PATH_MAX); + cached_data->nntp_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(cached_data->nntp_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + default: + return mailsession_parameters(get_ancestor(session), id, value); + } +} + +static int nntpdriver_cached_connect_stream(mailsession * session, + mailstream * s) +{ + return mailsession_connect_stream(get_ancestor(session), s); +} + +static int nntpdriver_cached_login(mailsession * session, + const char * userid, const char * password) +{ + return mailsession_login(get_ancestor(session), userid, password); +} + +static int nntpdriver_cached_logout(mailsession * session) +{ + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + return mailsession_logout(get_ancestor(session)); +} + +static int nntpdriver_cached_select_folder(mailsession * session, const char * mb) +{ + int r; + struct nntp_session_state_data * ancestor_data; + struct nntp_cached_session_state_data * cached_data; + int res; + char key[PATH_MAX]; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + r = mailsession_select_folder(get_ancestor(session), mb); + if (r != MAIL_NO_ERROR) + return r; + + if (ancestor_data->nntp_group_name == NULL) + return MAIL_ERROR_BAD_STATE; + + snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name); + + r = generic_cache_create_dir(key); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + snprintf(key, PATH_MAX, "%s/%s", cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name); + + r = generic_cache_create_dir(key); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int nntpdriver_cached_check_folder(mailsession * session) +{ + struct nntp_session_state_data * ancestor_data; + struct nntp_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + return MAIL_NO_ERROR; +} + + +static int nntpdriver_cached_status_folder(mailsession * session, + const char * mb, uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int res; + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + uint32_t i; + int r; + uint32_t recent; + uint32_t unseen; + uint32_t first; + uint32_t last; + uint32_t count; + uint32_t additionnal; + + r = nntpdriver_cached_select_folder(session, mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + read_article_seq(session, &first, &last); + + count = 0; + recent = 0; + unseen = 0; + + ancestor_data = get_ancestor_data(session); + cached_data = get_cached_data(session); + if (ancestor_data->nntp_group_name == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + if (ancestor_data->nntp_group_info->grp_first > first) + first = ancestor_data->nntp_group_info->grp_first; + if (last < first) + last = ancestor_data->nntp_group_info->grp_last; + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = first ; i <= last ; i++) { + struct mail_flags * flags; + + r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr, + i, &flags); + if (r == MAIL_NO_ERROR) { + if ((flags->fl_flags & MAIL_FLAG_CANCELLED) != 0) { + mail_flags_free(flags); + continue; + } + + count ++; + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + mail_flags_free(flags); + } + } + + if ((count == 0) && (first != last)) { + count = last - first + 1; + recent = count; + unseen = count; + } + + additionnal = ancestor_data->nntp_group_info->grp_last - last; + recent += additionnal; + unseen += additionnal; + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + * result_messages = count; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int nntpdriver_cached_messages_number(mailsession * session, + const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = nntpdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = messages; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_recent_number(mailsession * session, + const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = nntpdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_unseen_number(mailsession * session, + const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = nntpdriver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_list_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + return mailsession_list_folders(get_ancestor(session), mb, result); +} + +static int nntpdriver_cached_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + return mailsession_lsub_folders(get_ancestor(session), mb, result); +} + +static int nntpdriver_cached_subscribe_folder(mailsession * session, + const char * mb) +{ + return mailsession_subscribe_folder(get_ancestor(session), mb); +} + +static int nntpdriver_cached_unsubscribe_folder(mailsession * session, + const char * mb) +{ + return mailsession_unsubscribe_folder(get_ancestor(session), mb); +} + + + +/* messages operations */ + +static int nntpdriver_cached_append_message(mailsession * session, + const char * message, size_t size) +{ + return mailsession_append_message(get_ancestor(session), message, size); +} + +static int nntpdriver_cached_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + return nntpdriver_cached_append_message(session, message, size); +} + + + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields ** result) +{ + char keyname[PATH_MAX]; + int r; + struct mailimf_fields * fields; + int res; + + snprintf(keyname, PATH_MAX, "%i-envelope", num); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields * fields) +{ + int r; + int res; + char keyname[PATH_MAX]; + + snprintf(keyname, PATH_MAX, "%i-envelope", num); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +#define SEQ_FILENAME "articles-seq" + +static void read_article_seq(mailsession * session, + uint32_t * pfirst, uint32_t * plast) +{ + FILE * f; + struct nntp_session_state_data * ancestor_data; + uint32_t first; + uint32_t last; + char seq_filename[PATH_MAX]; + struct nntp_cached_session_state_data * cached_data; + int r; + + first = 0; + last = 0; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + if (ancestor_data->nntp_group_name == NULL) + return; + + snprintf(seq_filename, PATH_MAX, "%s/%s/%s", + cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, SEQ_FILENAME); + f = fopen(seq_filename, "r"); + + if (f != NULL) { + int fd; + + fd = fileno(f); + + r = maillock_read_lock(seq_filename, fd); + if (r == 0) { + MMAPString * mmapstr; + size_t cur_token; + char buf[sizeof(uint32_t) * 2]; + size_t read_size; + + read_size = fread(buf, 1, sizeof(uint32_t) * 2, f); + mmapstr = mmap_string_new_len(buf, read_size); + if (mmapstr != NULL) { + cur_token = 0; + r = mailimf_cache_int_read(mmapstr, &cur_token, &first); + r = mailimf_cache_int_read(mmapstr, &cur_token, &last); + + mmap_string_free(mmapstr); + } + + maillock_read_unlock(seq_filename, fd); + } + fclose(f); + } + + * pfirst = first; + * plast = last; +} + +static void write_article_seq(mailsession * session, + uint32_t first, uint32_t last) +{ + FILE * f; + struct nntp_session_state_data * ancestor_data; + char seq_filename[PATH_MAX]; + struct nntp_cached_session_state_data * cached_data; + int r; + int fd; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + if (ancestor_data->nntp_group_name == NULL) + return; + + snprintf(seq_filename, PATH_MAX, "%s/%s/%s", + cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, SEQ_FILENAME); + + fd = creat(seq_filename, S_IRUSR | S_IWUSR); + if (fd < 0) + return; + + f = fdopen(fd, "w"); + if (f != NULL) { + r = maillock_write_lock(seq_filename, fd); + if (r == 0) { + MMAPString * mmapstr; + size_t cur_token; + + mmapstr = mmap_string_new(""); + if (mmapstr != NULL) { + r = mail_serialize_clear(mmapstr, &cur_token); + if (r == MAIL_NO_ERROR) { + r = mailimf_cache_int_write(mmapstr, &cur_token, first); + r = mailimf_cache_int_write(mmapstr, &cur_token, last); + + fwrite(mmapstr->str, 1, mmapstr->len, f); + } + + mmap_string_free(mmapstr); + } + + maillock_write_unlock(seq_filename, fd); + } + fclose(f); + } + else + close(fd); +} + + +static void get_uid_from_filename(char * filename) +{ + char * p; + + if (strcmp(filename, SEQ_FILENAME) == 0) + * filename = 0; + + p = strstr(filename, "-header"); + if (p != NULL) + * p = 0; +} + +static int +nntpdriver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + struct nntp_cached_session_state_data * cached_data; + uint32_t first; + uint32_t last; + struct nntp_session_state_data * ancestor_data; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + int res; + char cache_dir[PATH_MAX]; + + cached_data = get_cached_data(session); + ancestor_data = get_ancestor_data(session); + + nntp_flags_store_process(cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, + cached_data->nntp_flags_store); + + if (ancestor_data->nntp_group_name == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + /* read articles sequence */ + + read_article_seq(session, &first, &last); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(filename_env, PATH_MAX, "%s/%s/%s", + cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, ENV_NAME); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, FLAGS_NAME); + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + + msg = carray_get(env_list->msg_tab, i); + + if ((msg->msg_index < first) || (msg->msg_index > last)) + continue; + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_fields = fields; + msg->msg_cached = TRUE; + } + } + } + + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = mailsession_get_envelopes_list(get_ancestor(session), env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + /* add flags */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) { + struct mail_flags * flags; + + r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr, + msg->msg_index, &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + else { + msg->msg_flags = mail_flags_new_empty(); + if (msg->msg_fields == NULL) { + msg->msg_flags->fl_flags |= MAIL_FLAG_CANCELLED; + mailmessage_check(msg); + } + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto close_db_env; + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = nntpdriver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_index, msg->msg_flags); + } + } + + first = 0; + last = 0; + if (carray_count(env_list->msg_tab) > 0) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, 0); + first = msg->msg_index; + + msg = carray_get(env_list->msg_tab, carray_count(env_list->msg_tab) - 1); + last = msg->msg_index; + } + + /* write articles sequence */ + + write_article_seq(session, first, last); + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + /* remove cache files */ + + snprintf(cache_dir, PATH_MAX, "%s/%s", + cached_data->nntp_cache_directory, ancestor_data->nntp_group_name); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + mmap_string_free(mmapstr); + + maildriver_message_cache_clean_up(cache_dir, env_list, + get_uid_from_filename); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int +nntpdriver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + return nntp_get_messages_list(get_ancestor(session), session, + nntp_cached_message_driver, result); +} + +static int nntpdriver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, nntp_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int nntpdriver_cached_noop(mailsession * session) +{ + return mailsession_noop(get_ancestor(session)); +} + +static int nntpdriver_cached_get_message_by_uid(mailsession * session, + const char * uid, + mailmessage ** result) +{ + uint32_t num; + char * p; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + num = strtoul(uid, &p, 10); + if ((p == uid) || (* p != '\0')) + return MAIL_ERROR_INVAL; + + return nntpdriver_cached_get_message(session, num, result); +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_cached.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_cached.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_cached.h,v 1.14 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef NNTPDRIVER_CACHED_H + +#define NNTPDRIVER_CACHED_H + +#include <libetpan/nntpdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * nntp_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,394 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_cached_message.c,v 1.19 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "nntpdriver_cached_message.h" + +#include <string.h> +#include <stdlib.h> + +#include "mail_cache_db.h" + +#include "mailmessage.h" +#include "mailmessage_tools.h" +#include "nntpdriver.h" +#include "nntpdriver_tools.h" +#include "nntpdriver_cached.h" +#include "nntpdriver_message.h" +#include "generic_cache.h" + +static int nntp_prefetch(mailmessage * msg_info); + +static void nntp_prefetch_free(struct generic_message_t * msg); + +static int nntp_initialize(mailmessage * msg_info); + +static int nntp_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int nntp_fetch_size(mailmessage * msg_info, + size_t * result); + +static void nntp_uninitialize(mailmessage * msg_info); + +static void nntp_flush(mailmessage * msg_info); + +static void nntp_check(mailmessage * msg_info); + +static int nntp_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static mailmessage_driver local_nntp_cached_message_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* msg_name */ "nntp-cached", + + /* msg_initialize */ nntp_initialize, + /* msg_uninitialize */ nntp_uninitialize, + + /* msg_flush */ nntp_flush, + /* msg_check */ nntp_check, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ nntp_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ nntp_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ nntp_get_flags, +#else + .msg_name = "nntp-cached", + + .msg_initialize = nntp_initialize, + .msg_uninitialize = nntp_uninitialize, + + .msg_flush = nntp_flush, + .msg_check = nntp_check, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = nntp_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = nntp_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = nntp_get_flags, +#endif +}; + +mailmessage_driver * nntp_cached_message_driver = +&local_nntp_cached_message_driver; + +static inline struct nntp_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailsession * get_ancestor_session(mailmessage * msg) +{ + return get_cached_session_data(msg)->nntp_ancestor; +} + +static inline struct nntp_session_state_data * +get_ancestor_session_data(mailmessage * msg) +{ + return get_ancestor_session(msg)->sess_data; +} + +static inline newsnntp * +get_nntp_session(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->nntp_session; +} + +static int nntp_prefetch(mailmessage * msg_info) +{ + char * msg_content; + size_t msg_length; + struct generic_message_t * msg; + int r; + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + char filename[PATH_MAX]; + + /* we try the cached message */ + + cached_data = get_cached_session_data(msg_info); + + ancestor_data = get_ancestor_session_data(msg_info); + + snprintf(filename, PATH_MAX, "%s/%s/%i", cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, msg_info->msg_index); + + r = generic_cache_read(filename, &msg_content, &msg_length); + if (r == MAIL_NO_ERROR) { + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; + } + + /* we get the message through the network */ + + r = nntpdriver_article(get_ancestor_session(msg_info), + msg_info->msg_index, &msg_content, + &msg_length); + + if (r != MAIL_NO_ERROR) + return r; + + /* we write the message cache */ + + generic_cache_store(filename, msg_content, msg_length); + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void nntp_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int nntp_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[20]; + + snprintf(static_uid, 20, "%u", msg_info->msg_index); + uid = strdup(static_uid); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = nntp_prefetch; + msg->msg_prefetch_free = nntp_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + + +static void nntp_uninitialize(mailmessage * msg_info) +{ + mailmessage_generic_uninitialize(msg_info); +} + +#define FLAGS_NAME "flags.db" + +static void nntp_flush(mailmessage * msg_info) +{ + mailmessage_generic_flush(msg_info); +} + + +static void nntp_check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_cached_session_data(msg_info)->nntp_flags_store, + msg_info); + /* ignore errors */ + } +} + +static int nntp_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + char * headers; + size_t headers_length; + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + int r; + char filename[PATH_MAX]; + + msg = msg_info->msg_data; + + if (msg->msg_message != NULL) + return mailmessage_generic_fetch_header(msg_info, + result, result_len); + + /* we try the cached message */ + + cached_data = get_cached_session_data(msg_info); + + ancestor_data = get_ancestor_session_data(msg_info); + + snprintf(filename, PATH_MAX, "%s/%s/%i-header", + cached_data->nntp_cache_directory, + ancestor_data->nntp_group_name, msg_info->msg_index); + + r = generic_cache_read(filename, &headers, &headers_length); + if (r == MAIL_NO_ERROR) { + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; + } + + /* we get the message through the network */ + + r = nntpdriver_head(get_ancestor_session(msg_info), msg_info->msg_index, + &headers, &headers_length); + if (r != MAIL_NO_ERROR) + return r; + + /* we write the message cache */ + + generic_cache_store(filename, headers, headers_length); + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +static int nntp_fetch_size(mailmessage * msg_info, + size_t * result) +{ + return nntpdriver_size(get_ancestor_session(msg_info), + msg_info->msg_index, result); +} + +static int nntp_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + int res; + MMAPString * mmapstr; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; + } + + flags = mail_flags_store_get(get_cached_session_data(msg_info)->nntp_flags_store, msg_info->msg_index); + + if (flags == NULL) { + struct nntp_cached_session_state_data * cached_data; + struct nntp_session_state_data * ancestor_data; + + cached_data = get_cached_session_data(msg_info); + + ancestor_data = get_ancestor_session_data(msg_info); + if (ancestor_data->nntp_group_name == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s/%s", + cached_data->nntp_flags_directory, + ancestor_data->nntp_group_name, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + r = nntpdriver_get_cached_flags(cache_db_flags, mmapstr, + msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + flags = mail_flags_new_empty(); + if (flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_cached_message.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_cached_message.h,v 1.6 2004/11/21 21:53:33 hoa Exp $ + */ + +#include <libetpan/mailmessage_types.h> + +#ifndef NNTPDRIVER_CACHED_MESSAGE_H + +#define NNTPDRIVER_CACHED_MESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * nntp_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_message.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_message.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,199 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_message.c,v 1.15 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "nntpdriver_message.h" + +#include "mailmessage_tools.h" +#include "nntpdriver_tools.h" +#include "nntpdriver.h" +#include "newsnntp.h" +#include <string.h> +#include <stdlib.h> + +static int nntp_prefetch(mailmessage * msg_info); + +static void nntp_prefetch_free(struct generic_message_t * msg); + +static int nntp_initialize(mailmessage * msg_info); + +static int nntp_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int nntp_fetch_size(mailmessage * msg_info, + size_t * result); + +static mailmessage_driver local_nntp_message_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + + /* msg_name */ "nntp", + + /* msg_initialize */ nntp_initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ NULL, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ nntp_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ nntp_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ NULL, +#else + .msg_name = "nntp", + + .msg_initialize = nntp_initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = NULL, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = nntp_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = nntp_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = NULL, +#endif +}; + +mailmessage_driver * nntp_message_driver = &local_nntp_message_driver; + +static int nntp_prefetch(mailmessage * msg_info) +{ + char * msg_content; + size_t msg_length; + struct generic_message_t * msg; + int r; + + r = nntpdriver_article(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void nntp_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int nntp_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + char static_uid[20]; + + snprintf(static_uid, 20, "%u", msg_info->msg_index); + uid = strdup(static_uid); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = nntp_prefetch; + msg->msg_prefetch_free = nntp_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + +static int nntp_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + char * headers; + size_t headers_length; + int r; + + msg = msg_info->msg_data; + + if (msg->msg_message != NULL) + return mailmessage_generic_fetch_header(msg_info, + result, result_len); + + r = nntpdriver_head(msg_info->msg_session, msg_info->msg_index, + &headers, &headers_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +static int nntp_fetch_size(mailmessage * msg_info, + size_t * result) +{ + return nntpdriver_size(msg_info->msg_session, msg_info->msg_index, result); +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_message.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_message.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_message.h,v 1.6 2004/11/21 21:53:33 hoa Exp $ + */ + +#ifndef NNTPDRIVER_MESSAGE_H + +#define NNTPDRIVER_MESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/nntpdriver_types.h> + +extern mailmessage_driver * nntp_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_tools.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,568 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_tools.c,v 1.21 2006/08/05 02:34:06 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "nntpdriver_tools.h" + +#include "mail.h" +#include "nntpdriver.h" +#include "nntpdriver_cached.h" +#include "newsnntp.h" +#include "maildriver_types.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mailmessage.h" +#include "mail_cache_db.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <string.h> +#include <stdlib.h> + +int nntpdriver_nntp_error_to_mail_error(int error) +{ + switch (error) { + case NEWSNNTP_NO_ERROR: + return MAIL_NO_ERROR; + + case NEWSNNTP_ERROR_STREAM: + return MAIL_ERROR_STREAM; + + case NEWSNNTP_ERROR_UNEXPECTED: + return MAIL_ERROR_UNKNOWN; + + case NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED: + return MAIL_ERROR_FOLDER_NOT_FOUND; + + case NEWSNNTP_ERROR_NO_ARTICLE_SELECTED: + case NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER: + case NEWSNNTP_ERROR_ARTICLE_NOT_FOUND: + return MAIL_ERROR_MSG_NOT_FOUND; + + case NEWSNNTP_ERROR_UNEXPECTED_RESPONSE: + case NEWSNNTP_ERROR_INVALID_RESPONSE: + return MAIL_ERROR_PARSE; + + case NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP: + return MAIL_ERROR_FOLDER_NOT_FOUND; + + case NEWSNNTP_ERROR_POSTING_NOT_ALLOWED: + return MAIL_ERROR_READONLY; + + case NEWSNNTP_ERROR_POSTING_FAILED: + return MAIL_ERROR_APPEND; + + case NEWSNNTP_ERROR_PROGRAM_ERROR: + return MAIL_ERROR_PROGRAM_ERROR; + + case NEWSNNTP_ERROR_NO_PERMISSION: + return MAIL_ERROR_NO_PERMISSION; + + case NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD: + case NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED: + return MAIL_ERROR_COMMAND_NOT_SUPPORTED; + + case NEWSNNTP_ERROR_CONNECTION_REFUSED: + return MAIL_ERROR_CONNECT; + + case NEWSNNTP_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case NEWSNNTP_ERROR_AUTHENTICATION_REJECTED: + return MAIL_ERROR_LOGIN; + + case NEWSNNTP_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + default: + return MAIL_ERROR_INVAL; + } +} + +static inline struct nntp_session_state_data * +session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline newsnntp * session_get_nntp_session(mailsession * session) +{ + return session_get_data(session)->nntp_session; +} + +static inline struct nntp_cached_session_state_data * +cached_session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * cached_session_get_ancestor(mailsession * session) +{ + return cached_session_get_data(session)->nntp_ancestor; +} + +static inline struct nntp_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return session_get_data(cached_session_get_ancestor(session)); +} + +static inline newsnntp * cached_session_get_nntp_session(mailsession * session) +{ + return session_get_nntp_session(cached_session_get_ancestor(session)); +} + + +int nntpdriver_authenticate_password(mailsession * session) +{ + struct nntp_session_state_data * data; + int r; + + data = session_get_data(session); + + if (data->nntp_password == NULL) + return MAIL_ERROR_LOGIN; + + r = newsnntp_authinfo_password(session_get_nntp_session(session), + data->nntp_password); + + return nntpdriver_nntp_error_to_mail_error(r); +} + +int nntpdriver_mode_reader(mailsession * session) +{ + int done; + int r; + + done = FALSE; + + do { + r = newsnntp_mode_reader(session_get_nntp_session(session)); + + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + done = TRUE; + break; + } + } + while (!done); + + return MAIL_NO_ERROR; +} + +int nntpdriver_authenticate_user(mailsession * session) +{ + struct nntp_session_state_data * data; + int r; + + data = session_get_data(session); + + if (data->nntp_userid == NULL) + return MAIL_ERROR_LOGIN; + + r = newsnntp_authinfo_username(session_get_nntp_session(session), + data->nntp_userid); + + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + return nntpdriver_authenticate_password(session); + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } +} + +int nntpdriver_article(mailsession * session, uint32_t index, + char ** result, + size_t * result_len) +{ + char * msg_content; + size_t msg_length; + int r; + int done; + + done = FALSE; + do { + r = newsnntp_article(session_get_nntp_session(session), + index, &msg_content, &msg_length); + + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (!done); + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; +} + +int nntpdriver_head(mailsession * session, uint32_t index, + char ** result, + size_t * result_len) +{ + char * headers; + size_t headers_length; + int r; + int done; + + done = FALSE; + do { + r = newsnntp_head(session_get_nntp_session(session), + index, &headers, &headers_length); + + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (!done); + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +int nntpdriver_size(mailsession * session, uint32_t index, + size_t * result) +{ + newsnntp * nntp; + struct newsnntp_xover_resp_item * item; + int r; + int done; + + nntp = session_get_nntp_session(session); + + done = FALSE; + do { + r = newsnntp_xover_single(nntp, index, &item); + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + } + while (!done); + + * result = item->ovr_size; + + xover_resp_item_free(item); + + return MAIL_NO_ERROR; +} + +int +nntpdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + uint32_t num, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + + snprintf(keyname, PATH_MAX, "%u-flags", num); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int +nntpdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + uint32_t num, + struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%u-flags", num); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +int nntpdriver_select_folder(mailsession * session, const char * mb) +{ + int r; + struct newsnntp_group_info * info; + newsnntp * nntp_session; + struct nntp_session_state_data * data; + char * new_name; + int done; + + data = session_get_data(session); + + if (!data->nntp_mode_reader) { + r = nntpdriver_mode_reader(session); + if (r != MAIL_NO_ERROR) + return r; + + data->nntp_mode_reader = TRUE; + } + + if (data->nntp_group_name != NULL) + if (strcmp(data->nntp_group_name, mb) == 0) + return MAIL_NO_ERROR; + + nntp_session = session_get_nntp_session(session); + + done = FALSE; + do { + r = newsnntp_group(nntp_session, mb, &info); + + switch (r) { + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME: + r = nntpdriver_authenticate_user(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD: + r = nntpdriver_authenticate_password(session); + if (r != MAIL_NO_ERROR) + return r; + break; + + case NEWSNNTP_NO_ERROR: + done = TRUE; + break; + + default: + return nntpdriver_nntp_error_to_mail_error(r); + } + + } + while (!done); + + new_name = strdup(mb); + if (new_name == NULL) + return MAIL_ERROR_MEMORY; + + if (data->nntp_group_name != NULL) + free(data->nntp_group_name); + data->nntp_group_name = new_name; + if (data->nntp_group_info != NULL) + newsnntp_group_free(data->nntp_group_info); + data->nntp_group_info = info; + + return MAIL_NO_ERROR; +} + + +int nntp_get_messages_list(mailsession * nntp_session, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + carray * tab; + struct mailmessage_list * env_list; + uint32_t i; + int res; + int r; + struct nntp_session_state_data * data; + struct newsnntp_group_info * group_info; + uint32_t max; + unsigned int cur; + + data = session_get_data(nntp_session); + + if (data->nntp_group_name == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + r = nntpdriver_select_folder(nntp_session, data->nntp_group_name); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + group_info = data->nntp_group_info; + + if (group_info == NULL) { + res = MAIL_ERROR_BAD_STATE; + goto err; + } + + max = group_info->grp_first; + if (data->nntp_max_articles != 0) { + if (group_info->grp_last - data->nntp_max_articles + 1 > max) + max = group_info->grp_last - data->nntp_max_articles + 1; + } + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = max ; i <= group_info->grp_last ; i++) { + mailmessage * msg; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, driver, i, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto free_list; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + env_list = mailmessage_list_new(tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + for(cur = 0 ; cur < carray_count(tab) ; cur ++) + mailmessage_free(carray_get(tab, cur)); + carray_free(tab); + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_tools.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_tools.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,88 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_tools.h,v 1.12 2006/06/07 15:10:01 smarinier Exp $ + */ + +#ifndef NNTPDRIVER_TOOLS_H + +#define NNTPDRIVER_TOOLS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mail_cache_db_types.h" +#include "nntpdriver_types.h" + +int nntpdriver_nntp_error_to_mail_error(int error); + +int nntpdriver_authenticate_password(mailsession * session); + +int nntpdriver_authenticate_user(mailsession * session); + +int nntpdriver_article(mailsession * session, uint32_t index, + char ** result, size_t * result_len); + +int nntpdriver_head(mailsession * session, uint32_t index, + char ** result, + size_t * result_len); + +int nntpdriver_size(mailsession * session, uint32_t index, + size_t * result); + +int +nntpdriver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + uint32_t num, + struct mail_flags ** result); + +int +nntpdriver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + uint32_t num, + struct mail_flags * flags); + +int nntpdriver_select_folder(mailsession * session, const char * mb); + +int nntp_get_messages_list(mailsession * nntp_session, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result); + +int nntpdriver_mode_reader(mailsession * session); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpdriver_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,146 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpdriver_types.h,v 1.9 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef NNTPDRIVER_TYPES_H + +#define NNTPDRIVER_TYPES_H + +#include <libetpan/libetpan-config.h> + +#include <libetpan/maildriver_types.h> +#include <libetpan/newsnntp.h> +#include <libetpan/clist.h> +#include <libetpan/generic_cache_types.h> +#include <libetpan/mailstorage_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* NNTP driver for session */ + +enum { + NNTPDRIVER_SET_MAX_ARTICLES = 1 +}; + +struct nntp_session_state_data { + newsnntp * nntp_session; + char * nntp_userid; + char * nntp_password; + + struct newsnntp_group_info * nntp_group_info; + char * nntp_group_name; + + clist * nntp_subscribed_list; + + uint32_t nntp_max_articles; + + int nntp_mode_reader; +}; + +/* cached NNTP driver for session */ + +enum { + /* the mapping of the parameters should be the same as for nntp */ + NNTPDRIVER_CACHED_SET_MAX_ARTICLES = 1, + /* cache specific */ + NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY, + NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY +}; + +struct nntp_cached_session_state_data { + mailsession * nntp_ancestor; + char nntp_cache_directory[PATH_MAX]; + char nntp_flags_directory[PATH_MAX]; + struct mail_flags_store * nntp_flags_store; +}; + + +/* nntp storage */ + +/* + nntp_mailstorage is the state data specific to the IMAP4rev1 storage. + + - storage this is the storage to initialize. + + - servername this is the name of the NNTP server + + - port is the port to connect to, on the server. + you give 0 to use the default port. + + - connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN or CONNECTION_TYPE_TLS. + + - auth_type is the authenticate mechanism to use. + The value can be NNTP_AUTH_TYPE_PLAIN. + + - login is the login of the POP3 account. + + - password is the password of the POP3 account. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache + + - flags_directory is the location of the flags +*/ + +struct nntp_mailstorage { + char * nntp_servername; + uint16_t nntp_port; + char * nntp_command; + int nntp_connection_type; + + int nntp_auth_type; + char * nntp_login; + char * nntp_password; + + int nntp_cached; + char * nntp_cache_directory; + char * nntp_flags_directory; +}; + +/* this is the type of NNTP authentication */ + +enum { + NNTP_AUTH_TYPE_PLAIN /* plain text authentication */ +}; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpstorage.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpstorage.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,279 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpstorage.c,v 1.16 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "nntpstorage.h" + +#include <stdlib.h> +#include <string.h> + +#include "maildriver.h" +#include "nntpdriver.h" +#include "nntpdriver_cached.h" +#include "mailstorage_tools.h" +#include "mail.h" + +/* nntp storage */ + +#define NNTP_DEFAULT_PORT 119 +#define NNTPS_DEFAULT_PORT 563 + +static int nntp_mailstorage_connect(struct mailstorage * storage); +static int nntp_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void nntp_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver nntp_mailstorage_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sto_name */ "nntp", + /* sto_connect */ nntp_mailstorage_connect, + /* sto_get_folder_session */ nntp_mailstorage_get_folder_session, + /* sto_uninitialize */ nntp_mailstorage_uninitialize, +#else + .sto_name = "nntp", + .sto_connect = nntp_mailstorage_connect, + .sto_get_folder_session = nntp_mailstorage_get_folder_session, + .sto_uninitialize = nntp_mailstorage_uninitialize, +#endif +}; + +LIBETPAN_EXPORT +int nntp_mailstorage_init(struct mailstorage * storage, + const char * nn_servername, uint16_t nn_port, + const char * nn_command, + int nn_connection_type, int nn_auth_type, + const char * nn_login, const char * nn_password, + int nn_cached, const char * nn_cache_directory, const char * nn_flags_directory) +{ + struct nntp_mailstorage * nntp_storage; + int res; + + nntp_storage = malloc(sizeof(* nntp_storage)); + if (nntp_storage == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + nntp_storage->nntp_servername = strdup(nn_servername); + if (nntp_storage->nntp_servername == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + nntp_storage->nntp_connection_type = nn_connection_type; + + if (nn_port == 0) { + switch (nn_connection_type) { + case CONNECTION_TYPE_PLAIN: + case CONNECTION_TYPE_COMMAND: + nn_port = NNTP_DEFAULT_PORT; + break; + + case CONNECTION_TYPE_TLS: + case CONNECTION_TYPE_COMMAND_TLS: + nn_port = NNTPS_DEFAULT_PORT; + break; + + default: + res = MAIL_ERROR_INVAL; + goto free_servername; + } + } + + nntp_storage->nntp_port = nn_port; + + if (nn_command != NULL) { + nntp_storage->nntp_command = strdup(nn_command); + if (nntp_storage->nntp_command == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_servername; + } + } + else + nntp_storage->nntp_command = NULL; + + nntp_storage->nntp_auth_type = nn_auth_type; + + if (nn_login != NULL) { + nntp_storage->nntp_login = strdup(nn_login); + if (nntp_storage->nntp_login == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_command; + } + } + else + nntp_storage->nntp_login = NULL; + + if (nn_password != NULL) { + nntp_storage->nntp_password = strdup(nn_password); + if (nntp_storage->nntp_password == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_login; + } + } + else + nntp_storage->nntp_password = NULL; + + nntp_storage->nntp_cached = nn_cached; + + if (nn_cached && (nn_cache_directory != NULL) && + (nn_flags_directory != NULL)) { + nntp_storage->nntp_cache_directory = strdup(nn_cache_directory); + if (nntp_storage->nntp_cache_directory == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_password; + } + nntp_storage->nntp_flags_directory = strdup(nn_flags_directory); + if (nntp_storage->nntp_flags_directory == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_cache_directory; + } + } + else { + nntp_storage->nntp_cached = FALSE; + nntp_storage->nntp_cache_directory = NULL; + nntp_storage->nntp_flags_directory = NULL; + } + + storage->sto_data = nntp_storage; + storage->sto_driver = &nntp_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(nntp_storage->nntp_cache_directory); + free_password: + free(nntp_storage->nntp_password); + free_login: + free(nntp_storage->nntp_login); + free_command: + free(nntp_storage->nntp_command); + free_servername: + free(nntp_storage->nntp_servername); + free: + free(nntp_storage); + err: + return res; +} + +static void nntp_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct nntp_mailstorage * nntp_storage; + + nntp_storage = storage->sto_data; + + if (nntp_storage->nntp_flags_directory != NULL) + free(nntp_storage->nntp_flags_directory); + if (nntp_storage->nntp_cache_directory != NULL) + free(nntp_storage->nntp_cache_directory); + if (nntp_storage->nntp_password != NULL) + free(nntp_storage->nntp_password); + if (nntp_storage->nntp_login != NULL) + free(nntp_storage->nntp_login); + if (nntp_storage->nntp_command != NULL) + free(nntp_storage->nntp_command); + free(nntp_storage->nntp_servername); + free(nntp_storage); + + storage->sto_data = NULL; +} + +static int nntp_mailstorage_connect(struct mailstorage * storage) +{ + struct nntp_mailstorage * nntp_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + + nntp_storage = storage->sto_data; + + if (nntp_storage->nntp_cached) + driver = nntp_cached_session_driver; + else + driver = nntp_session_driver; + + r = mailstorage_generic_connect(driver, + nntp_storage->nntp_servername, + nntp_storage->nntp_port, nntp_storage->nntp_command, + nntp_storage->nntp_connection_type, + NNTPDRIVER_CACHED_SET_CACHE_DIRECTORY, + nntp_storage->nntp_cache_directory, + NNTPDRIVER_CACHED_SET_FLAGS_DIRECTORY, + nntp_storage->nntp_flags_directory, + &session); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto err; + } + + r = mailstorage_generic_auth(session, r, + nntp_storage->nntp_connection_type, + nntp_storage->nntp_login, + nntp_storage->nntp_password); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int nntp_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + int r; + + r = mailsession_select_folder(storage->sto_session, pathname); + + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpstorage.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/nntp/nntpstorage.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,94 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: nntpstorage.h,v 1.10 2006/06/02 15:44:29 smarinier Exp $ + */ + +#ifndef NNTPSTORAGE_H + +#define NNTPSTORAGE_H + +#include <libetpan/nntpdriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + nntp_mailstorage_init is the constructor for a NNTP storage + + @param storage this is the storage to initialize. + + @param servername this is the name of the NNTP server + + @param port is the port to connect to, on the server. + you give 0 to use the default port. + + @param command the command used to connect to the server instead of + allowing normal TCP connections to be used. + + @param connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS, + CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS, + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,. + + @param auth_type is the authenticate mechanism to use. + The value can be NNTP_AUTH_TYPE_PLAIN. + + @param login is the login of the POP3 account. + + @param password is the password of the POP3 account. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +LIBETPAN_EXPORT +int nntp_mailstorage_init(struct mailstorage * storage, + const char * nntp_servername, uint16_t nntp_port, + const char * nntp_command, + int nntp_connection_type, int nntp_auth_type, + const char * nntp_login, const char * nntp_password, + int nntp_cached, const char * nntp_cache_directory, + const char * nntp_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,30 @@ +top_builddir = ../../../.. + +HEADERS = \ + pop3driver.h \ + pop3driver_cached.h \ + pop3driver_cached_message.h \ + pop3driver_message.h \ + pop3driver_types.h \ + pop3storage.h + + +SOURCES = \ + pop3driver.c \ + pop3driver_cached.c \ + pop3driver_cached_message.c \ + pop3driver_message.c \ + pop3driver_tools.c \ + pop3storage.c + + +TARGET = libpop3 +INCLUDES = -I../../interface \ + -I../../tools \ + -I$(srcdir)/low-level/pop3 \ + -I$(srcdir)/low-level/mime \ + -I$(srcdir)/low-level/imf \ + -I$(srcdir)/data-types + + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,469 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver.c,v 1.38 2006/06/28 06:13:47 skunk Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "pop3driver.h" + +#include <string.h> +#include <stdlib.h> + +#include "pop3driver_message.h" +#include "maildriver_tools.h" +#include "pop3driver_tools.h" +#include "mailmessage.h" + +static int pop3driver_initialize(mailsession * session); + +static void pop3driver_uninitialize(mailsession * session); + +static int pop3driver_parameters(mailsession * session, + int id, void * value); + +static int pop3driver_connect_stream(mailsession * session, mailstream * s); + +static int pop3driver_starttls(mailsession * session); + +static int pop3driver_login(mailsession * session, + const char * userid, const char * password); + +static int pop3driver_logout(mailsession * session); + +static int pop3driver_noop(mailsession * session); + +static int pop3driver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int pop3driver_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +static int pop3driver_remove_message(mailsession * session, uint32_t num); + +static int pop3driver_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int pop3driver_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int pop3driver_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +static mailsession_driver local_pop3_session_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + + /* sess_name */ "pop3", + + /* sess_initialize */ pop3driver_initialize, + /* sess_uninitialize */ pop3driver_uninitialize, + + /* sess_parameters */ pop3driver_parameters, + + /* sess_connect_stream */ pop3driver_connect_stream, + /* sess_connect_path */ NULL, + /* sess_starttls */ pop3driver_starttls, + /* sess_login */ pop3driver_login, + /* sess_logout */ pop3driver_logout, + /* sess_noop */ pop3driver_noop, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ NULL, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ NULL, + /* sess_expunge_folder */ NULL, + /* sess_status_folder */ pop3driver_status_folder, + /* sess_messages_number */ pop3driver_messages_number, + /* sess_recent_number */ pop3driver_messages_number, + /* sess_unseen_number */ pop3driver_messages_number, + /* sess_list_folders */ NULL, + /* sess_lsub_folders */ NULL, + /* sess_subscribe_folder */ NULL, + /* sess_unsubscribe_folder */ NULL, + + /* sess_append_message */ NULL, + /* sess_append_message_flags */ NULL, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ pop3driver_get_message, + /* sess_get_message_by_uid */ NULL, + + /* sess_get_messages_list */ pop3driver_get_messages_list, + /* sess_get_envelopes_list */ maildriver_generic_get_envelopes_list, + /* sess_remove_message */ pop3driver_remove_message, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ pop3driver_login_sasl, + +#else + .sess_name = "pop3", + + .sess_initialize = pop3driver_initialize, + .sess_uninitialize = pop3driver_uninitialize, + + .sess_parameters = pop3driver_parameters, + + .sess_connect_stream = pop3driver_connect_stream, + .sess_connect_path = NULL, + .sess_starttls = pop3driver_starttls, + .sess_login = pop3driver_login, + .sess_logout = pop3driver_logout, + .sess_noop = pop3driver_noop, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = NULL, + .sess_examine_folder = NULL, + .sess_select_folder = NULL, + .sess_expunge_folder = NULL, + .sess_status_folder = pop3driver_status_folder, + .sess_messages_number = pop3driver_messages_number, + .sess_recent_number = pop3driver_messages_number, + .sess_unseen_number = pop3driver_messages_number, + .sess_list_folders = NULL, + .sess_lsub_folders = NULL, + .sess_subscribe_folder = NULL, + .sess_unsubscribe_folder = NULL, + + .sess_append_message = NULL, + .sess_append_message_flags = NULL, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = pop3driver_get_messages_list, + .sess_get_envelopes_list = maildriver_generic_get_envelopes_list, + .sess_remove_message = pop3driver_remove_message, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = pop3driver_get_message, + .sess_get_message_by_uid = NULL, + .sess_login_sasl = pop3driver_login_sasl, +#endif +}; + +mailsession_driver * pop3_session_driver = &local_pop3_session_driver; + +static inline struct pop3_session_state_data * +get_data(mailsession * session) +{ + return session->sess_data; +} + +static mailpop3 * get_pop3_session(mailsession * session) +{ + return get_data(session)->pop3_session; +} + +static int pop3driver_initialize(mailsession * session) +{ + struct pop3_session_state_data * data; + mailpop3 * pop3; + + pop3 = mailpop3_new(0, NULL); + if (session == NULL) + goto err; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto free; + + data->pop3_session = pop3; + data->pop3_auth_type = POP3DRIVER_AUTH_TYPE_PLAIN; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free: + mailpop3_free(pop3); + err: + return MAIL_ERROR_MEMORY; +} + +static void pop3driver_uninitialize(mailsession * session) +{ + struct pop3_session_state_data * data; + + data = get_data(session); + + mailpop3_free(data->pop3_session); + free(data); + + session->sess_data = data; +} + +static int pop3driver_connect_stream(mailsession * session, mailstream * s) +{ + int r; + + r = mailpop3_connect(get_pop3_session(session), s); + + switch (r) { + case MAILPOP3_NO_ERROR: + return MAIL_NO_ERROR_NON_AUTHENTICATED; + + default: + return pop3driver_pop3_error_to_mail_error(r); + } +} + +static int pop3driver_starttls(mailsession * session) +{ + int r; + int fd; + mailstream_low * low; + mailstream_low * new_low; + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + r = mailpop3_stls(pop3); + + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + low = mailstream_get_low(pop3->pop3_stream); + fd = mailstream_low_get_fd(low); + if (fd == -1) + return MAIL_ERROR_STREAM; + + new_low = mailstream_low_tls_open(fd); + if (new_low == NULL) + return MAIL_ERROR_STREAM; + mailstream_low_free(low); + mailstream_set_low(pop3->pop3_stream, new_low); + + return MAIL_NO_ERROR; +} + +static int pop3driver_parameters(mailsession * session, + int id, void * value) +{ + struct pop3_session_state_data * data; + + data = get_data(session); + + switch (id) { + case POP3DRIVER_SET_AUTH_TYPE: + { + int * param; + + param = value; + + data->pop3_auth_type = * param; + return MAIL_NO_ERROR; + } + } + + return MAIL_ERROR_INVAL; +} + +static int pop3driver_login(mailsession * session, + const char * userid, const char * password) +{ + int r; + carray * msg_tab; + struct pop3_session_state_data * data; + + data = get_data(session); + + switch (data->pop3_auth_type) { + case POP3DRIVER_AUTH_TYPE_TRY_APOP: + r = mailpop3_login_apop(get_pop3_session(session), userid, password); + if (r != MAILPOP3_NO_ERROR) + r = mailpop3_login(get_pop3_session(session), userid, password); + break; + + case POP3DRIVER_AUTH_TYPE_APOP: + r = mailpop3_login_apop(get_pop3_session(session), userid, password); + break; + + default: + case POP3DRIVER_AUTH_TYPE_PLAIN: + r = mailpop3_login(get_pop3_session(session), userid, password); + break; + } + + mailpop3_list(get_pop3_session(session), &msg_tab); + + return pop3driver_pop3_error_to_mail_error(r); +} + +static int pop3driver_logout(mailsession * session) +{ + int r; + + r = mailpop3_quit(get_pop3_session(session)); + + return pop3driver_pop3_error_to_mail_error(r); +} + +static int pop3driver_noop(mailsession * session) +{ + int r; + + r = mailpop3_noop(get_pop3_session(session)); + + return pop3driver_pop3_error_to_mail_error(r); +} + +static int pop3driver_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, + uint32_t * result_recent, + uint32_t * result_unseen) +{ + uint32_t count; + int r; + + r = pop3driver_messages_number(session, mb, &count); + if (r != MAIL_NO_ERROR) + return r; + + * result_messages = count; + * result_recent = count; + * result_unseen = count; + + return MAIL_NO_ERROR; +} + +static int pop3driver_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + carray * msg_tab; + + mailpop3_list(get_pop3_session(session), &msg_tab); + + * result = carray_count(msg_tab) - + get_pop3_session(session)->pop3_deleted_count; + + return MAIL_NO_ERROR; +} + + +/* messages operations */ + +static int pop3driver_remove_message(mailsession * session, uint32_t num) +{ + mailpop3 * pop3; + int r; + + pop3 = get_pop3_session(session); + + r = mailpop3_dele(pop3, num); + switch (r) { + case MAILPOP3_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + + case MAILPOP3_ERROR_NO_SUCH_MESSAGE: + return MAIL_ERROR_MSG_NOT_FOUND; + + case MAILPOP3_ERROR_STREAM: + return MAIL_ERROR_STREAM; + + case MAILPOP3_NO_ERROR: + return MAIL_NO_ERROR; + + default: + return MAIL_ERROR_REMOVE; + } +} + +static int pop3driver_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + return pop3_get_messages_list(pop3, session, + pop3_message_driver, result); +} + +static int pop3driver_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, pop3_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int pop3driver_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ + int r; + + r = mailpop3_auth(get_pop3_session(session), + auth_type, server_fqdn, local_ip_port, remote_ip_port, + login, auth_name, password, realm); + + return pop3driver_pop3_error_to_mail_error(r); +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver.h,v 1.15 2004/11/21 21:53:34 hoa Exp $ + */ + +#ifndef POP3DRIVER_H + +#define POP3DRIVER_H + +#include <libetpan/pop3driver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailsession_driver * pop3_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_cached.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_cached.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,980 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_cached.c,v 1.47 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "pop3driver_cached.h" + +#include "libetpan-config.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <stdlib.h> + +#include "mail.h" +#include "mail_cache_db.h" + +#include "maildriver.h" +#include "mailmessage.h" +#include "pop3driver.h" +#include "mailpop3.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "pop3driver_cached_message.h" +#include "pop3driver_tools.h" +#include "maildriver_tools.h" + +static int pop3driver_cached_initialize(mailsession * session); + +static void pop3driver_cached_uninitialize(mailsession * session); + +static int pop3driver_cached_parameters(mailsession * session, + int id, void * value); + +static int pop3driver_cached_connect_stream(mailsession * session, + mailstream * s); + +static int pop3driver_cached_starttls(mailsession * session); + +static int pop3driver_cached_login(mailsession * session, + const char * userid, const char * password); + +static int pop3driver_cached_logout(mailsession * session); + +static int pop3driver_cached_check_folder(mailsession * session); + +static int pop3driver_cached_noop(mailsession * session); + +static int pop3driver_cached_expunge_folder(mailsession * session); + +static int pop3driver_cached_status_folder(mailsession * session, + const char * mb, uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +static int pop3driver_cached_messages_number(mailsession * session, + const char * mb, + uint32_t * result); + +static int pop3driver_cached_recent_number(mailsession * session, + const char * mb, + uint32_t * result); + +static int pop3driver_cached_unseen_number(mailsession * session, + const char * mb, + uint32_t * result); + +static int pop3driver_cached_remove_message(mailsession * session, + uint32_t num); + +static int +pop3driver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +static int +pop3driver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +static int pop3driver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +static int pop3driver_cached_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + +static int pop3driver_cached_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +static mailsession_driver local_pop3_cached_session_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sess_name */ "pop3-cached", + + /* sess_initialize */ pop3driver_cached_initialize, + /* sess_uninitialize */ pop3driver_cached_uninitialize, + + /* sess_parameters */ pop3driver_cached_parameters, + + /* sess_connect_stream */ pop3driver_cached_connect_stream, + /* sess_connect_path */ NULL, + /* sess_starttls */ pop3driver_cached_starttls, + /* sess_login */ pop3driver_cached_login, + /* sess_logout */ pop3driver_cached_logout, + /* sess_noop */ pop3driver_cached_noop, + + /* sess_build_folder_name */ NULL, + /* sess_create_folder */ NULL, + /* sess_delete_folder */ NULL, + /* sess_rename_folder */ NULL, + /* sess_check_folder */ pop3driver_cached_check_folder, + /* sess_examine_folder */ NULL, + /* sess_select_folder */ NULL, + /* sess_expunge_folder */ pop3driver_cached_expunge_folder, + /* sess_status_folder */ pop3driver_cached_status_folder, + /* sess_messages_number */ pop3driver_cached_messages_number, + /* sess_recent_number */ pop3driver_cached_recent_number, + /* sess_unseen_number */ pop3driver_cached_unseen_number, + /* sess_list_folders */ NULL, + /* sess_lsub_folders */ NULL, + /* sess_subscribe_folder */ NULL, + /* sess_unsubscribe_folder */ NULL, + + /* sess_append_message */ NULL, + /* sess_append_message_flags */ NULL, + /* sess_copy_message */ NULL, + /* sess_move_message */ NULL, + + /* sess_get_message */ pop3driver_cached_get_message, + /* sess_get_message_by_uid */ pop3driver_cached_get_message_by_uid, + + /* sess_get_messages_list */ pop3driver_cached_get_messages_list, + /* sess_get_envelopes_list */ pop3driver_cached_get_envelopes_list, + /* sess_remove_message */ pop3driver_cached_remove_message, +#if 0 + /* sess_search_messages */ maildriver_generic_search_messages, +#endif + /* sess_login_sasl */ pop3driver_cached_login_sasl, + +#else + .sess_name = "pop3-cached", + + .sess_initialize = pop3driver_cached_initialize, + .sess_uninitialize = pop3driver_cached_uninitialize, + + .sess_parameters = pop3driver_cached_parameters, + + .sess_connect_stream = pop3driver_cached_connect_stream, + .sess_connect_path = NULL, + .sess_starttls = pop3driver_cached_starttls, + .sess_login = pop3driver_cached_login, + .sess_logout = pop3driver_cached_logout, + .sess_noop = pop3driver_cached_noop, + + .sess_build_folder_name = NULL, + .sess_create_folder = NULL, + .sess_delete_folder = NULL, + .sess_rename_folder = NULL, + .sess_check_folder = pop3driver_cached_check_folder, + .sess_examine_folder = NULL, + .sess_select_folder = NULL, + .sess_expunge_folder = pop3driver_cached_expunge_folder, + .sess_status_folder = pop3driver_cached_status_folder, + .sess_messages_number = pop3driver_cached_messages_number, + .sess_recent_number = pop3driver_cached_recent_number, + .sess_unseen_number = pop3driver_cached_unseen_number, + .sess_list_folders = NULL, + .sess_lsub_folders = NULL, + .sess_subscribe_folder = NULL, + .sess_unsubscribe_folder = NULL, + + .sess_append_message = NULL, + .sess_append_message_flags = NULL, + .sess_copy_message = NULL, + .sess_move_message = NULL, + + .sess_get_messages_list = pop3driver_cached_get_messages_list, + .sess_get_envelopes_list = pop3driver_cached_get_envelopes_list, + .sess_remove_message = pop3driver_cached_remove_message, +#if 0 + .sess_search_messages = maildriver_generic_search_messages, +#endif + + .sess_get_message = pop3driver_cached_get_message, + .sess_get_message_by_uid = pop3driver_cached_get_message_by_uid, + .sess_login_sasl = pop3driver_cached_login_sasl, +#endif +}; + +mailsession_driver * pop3_cached_session_driver = +&local_pop3_cached_session_driver; + +#define ENV_NAME "env.db" +#define FLAGS_NAME "flags.db" + + +static inline struct pop3_cached_session_state_data * +get_cached_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * get_ancestor(mailsession * session) +{ + return get_cached_data(session)->pop3_ancestor; +} + +static inline struct pop3_session_state_data * +get_ancestor_data(mailsession * session) +{ + return get_ancestor(session)->sess_data; +} + +static inline mailpop3 * get_pop3_session(mailsession * session) +{ + return get_ancestor_data(session)->pop3_session; +} + +static int pop3driver_cached_initialize(mailsession * session) +{ + struct pop3_cached_session_state_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + goto err; + + data->pop3_flags_store = mail_flags_store_new(); + if (data->pop3_flags_store == NULL) + goto free_data; + + data->pop3_ancestor = mailsession_new(pop3_session_driver); + if (data->pop3_ancestor == NULL) + goto free_store; + + data->pop3_flags_hash = chash_new(128, CHASH_COPYNONE); + if (data->pop3_flags_hash == NULL) + goto free_session; + + session->sess_data = data; + + return MAIL_NO_ERROR; + + free_session: + mailsession_free(data->pop3_ancestor); + free_store: + mail_flags_store_free(data->pop3_flags_store); + free_data: + free(data); + err: + return MAIL_ERROR_MEMORY; +} + +static int pop3_flags_store_process(char * flags_directory, + struct mail_flags_store * flags_store) +{ + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + int res; + + if (carray_count(flags_store->fls_tab) == 0) + return MAIL_NO_ERROR; + + snprintf(filename_flags, PATH_MAX, "%s/%s", + flags_directory, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + r = pop3driver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + mail_flags_store_clear(flags_store); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static void pop3driver_cached_uninitialize(mailsession * session) +{ + struct pop3_cached_session_state_data * data; + + data = get_cached_data(session); + + pop3_flags_store_process(data->pop3_flags_directory, + data->pop3_flags_store); + + mail_flags_store_free(data->pop3_flags_store); + + chash_free(data->pop3_flags_hash); + mailsession_free(data->pop3_ancestor); + free(data); + + session->sess_data = data; +} + +static int pop3driver_cached_check_folder(mailsession * session) +{ + struct pop3_cached_session_state_data * pop3_data; + + pop3_data = get_cached_data(session); + + pop3_flags_store_process(pop3_data->pop3_flags_directory, + pop3_data->pop3_flags_store); + + return MAIL_NO_ERROR; +} + +static int pop3driver_cached_parameters(mailsession * session, + int id, void * value) +{ + struct pop3_cached_session_state_data * data; + int r; + + data = get_cached_data(session); + + switch (id) { + case POP3DRIVER_CACHED_SET_CACHE_DIRECTORY: + strncpy(data->pop3_cache_directory, value, PATH_MAX); + data->pop3_cache_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->pop3_cache_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + case POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY: + strncpy(data->pop3_flags_directory, value, PATH_MAX); + data->pop3_flags_directory[PATH_MAX - 1] = '\0'; + + r = generic_cache_create_dir(data->pop3_flags_directory); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + + default: + return mailsession_parameters(data->pop3_ancestor, id, value); + } +} + +static int pop3driver_cached_connect_stream(mailsession * session, + mailstream * s) +{ + int r; + + r = mailsession_connect_stream(get_ancestor(session), s); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +static int pop3driver_cached_starttls(mailsession * session) +{ + return mailsession_starttls(get_ancestor(session)); +} + + +static int pop3driver_cached_login(mailsession * session, + const char * userid, const char * password) +{ + return mailsession_login(get_ancestor(session), userid, password); +} + +static int pop3driver_cached_logout(mailsession * session) +{ + struct pop3_cached_session_state_data * cached_data; + + cached_data = get_cached_data(session); + + pop3_flags_store_process(cached_data->pop3_flags_directory, + cached_data->pop3_flags_store); + + return mailsession_logout(get_ancestor(session)); +} + +static int pop3driver_cached_noop(mailsession * session) +{ + return mailsession_noop(get_ancestor(session)); +} + +static int pop3driver_cached_expunge_folder(mailsession * session) +{ + int res; + struct pop3_cached_session_state_data * cached_data; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + carray * msg_tab; + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + cached_data = get_cached_data(session); + + pop3_flags_store_process(cached_data->pop3_flags_directory, + cached_data->pop3_flags_store); + + snprintf(filename_flags, PATH_MAX, "%s/%s", + cached_data->pop3_flags_directory, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + mailpop3_list(pop3, &msg_tab); + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * pop3_info; + struct mail_flags * flags; + + pop3_info = carray_get(msg_tab, i); + if (pop3_info == NULL) + continue; + + if (pop3_info->msg_deleted) + continue; + + r = pop3driver_get_cached_flags(cache_db_flags, mmapstr, + session, pop3_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) + continue; + + if (flags->fl_flags & MAIL_FLAG_DELETED) { + r = mailpop3_dele(pop3, pop3_info->msg_index); + } + + mail_flags_free(flags); + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int pop3driver_cached_status_folder(mailsession * session, + const char * mb, uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + int res; + struct pop3_cached_session_state_data * cached_data; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + unsigned int i; + int r; + carray * msg_tab; + mailpop3 * pop3; + uint32_t recent; + uint32_t unseen; + + recent = 0; + unseen = 0; + + pop3 = get_pop3_session(session); + + cached_data = get_cached_data(session); + + pop3_flags_store_process(cached_data->pop3_flags_directory, + cached_data->pop3_flags_store); + + snprintf(filename_flags, PATH_MAX, "%s/%s", + cached_data->pop3_flags_directory, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + mailpop3_list(pop3, &msg_tab); + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * pop3_info; + struct mail_flags * flags; + + pop3_info = carray_get(msg_tab, i); + if (pop3_info == NULL) + continue; + + if (pop3_info->msg_deleted) + continue; + + r = pop3driver_get_cached_flags(cache_db_flags, mmapstr, + session, pop3_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + recent ++; + unseen ++; + continue; + } + + if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) { + recent ++; + } + if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) { + unseen ++; + } + mail_flags_free(flags); + + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + + * result_messages = carray_count(msg_tab) - pop3->pop3_deleted_count; + * result_recent = recent; + * result_unseen = unseen; + + return MAIL_NO_ERROR; + + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} + +static int pop3driver_cached_messages_number(mailsession * session, + const char * mb, + uint32_t * result) +{ + return mailsession_messages_number(get_ancestor(session), mb, result); +} + +static int pop3driver_cached_recent_number(mailsession * session, + const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = pop3driver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = recent; + + return MAIL_NO_ERROR; +} + +static int pop3driver_cached_unseen_number(mailsession * session, + const char * mb, + uint32_t * result) +{ + uint32_t messages; + uint32_t recent; + uint32_t unseen; + int r; + + r = pop3driver_cached_status_folder(session, mb, + &messages, &recent, &unseen); + if (r != MAIL_NO_ERROR) + return r; + + * result = unseen; + + return MAIL_NO_ERROR; +} + +/* messages operations */ + +static int pop3driver_cached_remove_message(mailsession * session, + uint32_t num) +{ + return mailsession_remove_message(get_ancestor(session), num); +} + +static int +pop3driver_cached_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + return pop3_get_messages_list(pop3, session, + pop3_cached_message_driver, result); +} + + +static int +get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mailpop3_msg_info * info; + struct mailimf_fields * fields; + int res; + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + r = mailpop3_get_msg_info(pop3, num, &info); + switch (r) { + case MAILPOP3_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + case MAILPOP3_ERROR_NO_SUCH_MESSAGE: + return MAIL_ERROR_MSG_NOT_FOUND; + case MAILPOP3_NO_ERROR: + break; + default: + return MAIL_ERROR_FETCH; + } + + snprintf(keyname, PATH_MAX, "%s-envelope", info->msg_uidl); + + r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static int +write_cached_envelope(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, uint32_t num, + struct mailimf_fields * fields) +{ + int r; + char keyname[PATH_MAX]; + int res; + struct mailpop3_msg_info * info; + mailpop3 * pop3; + + pop3 = get_pop3_session(session); + + r = mailpop3_get_msg_info(pop3, num, &info); + switch (r) { + case MAILPOP3_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + case MAILPOP3_ERROR_NO_SUCH_MESSAGE: + return MAIL_ERROR_MSG_NOT_FOUND; + case MAILPOP3_NO_ERROR: + break; + default: + return MAIL_ERROR_FETCH; + } + + snprintf(keyname, PATH_MAX, "%s-envelope", info->msg_uidl); + + r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +static void get_uid_from_filename(char * filename) +{ + char * p; + + p = strstr(filename, "-header"); + if (p != NULL) + * p = 0; +} + +static int +pop3driver_cached_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned int i; + struct pop3_cached_session_state_data * cached_data; + char filename_env[PATH_MAX]; + char filename_flags[PATH_MAX]; + struct mail_cache_db * cache_db_env; + struct mail_cache_db * cache_db_flags; + MMAPString * mmapstr; + int res; + + cached_data = get_cached_data(session); + + pop3_flags_store_process(cached_data->pop3_flags_directory, + cached_data->pop3_flags_store); + + snprintf(filename_env, PATH_MAX, "%s/%s", + cached_data->pop3_cache_directory, ENV_NAME); + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + snprintf(filename_flags, PATH_MAX, "%s/%s", + cached_data->pop3_flags_directory, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto close_db_env; + } + + /* fill with cached */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailimf_fields * fields; + struct mail_flags * flags; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + r = get_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, &fields); + if (r == MAIL_NO_ERROR) { + msg->msg_cached = TRUE; + msg->msg_fields = fields; + } + } + + if (msg->msg_flags == NULL) { + r = pop3driver_get_cached_flags(cache_db_flags, mmapstr, + session, msg->msg_index, &flags); + if (r == MAIL_NO_ERROR) { + msg->msg_flags = flags; + } + } + } + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + + r = maildriver_generic_get_envelopes_list(session, env_list); + + if (r != MAIL_NO_ERROR) { + res = r; + goto free_mmapstr; + } + + /* add flags */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) + msg->msg_flags = mail_flags_new_empty(); + } + + r = mail_cache_db_open_lock(filename_env, &cache_db_env); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto close_db_env; + } + + /* must write cache */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields != NULL) { + if (!msg->msg_cached) { + r = write_cached_envelope(cache_db_env, mmapstr, + session, msg->msg_index, msg->msg_fields); + } + } + + if (msg->msg_flags != NULL) { + r = pop3driver_write_cached_flags(cache_db_flags, mmapstr, + msg->msg_uid, msg->msg_flags); + } + } + + /* flush cache */ + + maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list); + + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + mail_cache_db_close_unlock(filename_env, cache_db_env); + mmap_string_free(mmapstr); + + /* remove cache files */ + + maildriver_message_cache_clean_up(cached_data->pop3_cache_directory, + env_list, get_uid_from_filename); + + return MAIL_NO_ERROR; + + close_db_env: + mail_cache_db_close_unlock(filename_env, cache_db_env); + free_mmapstr: + mmap_string_free(mmapstr); + err: + return res; +} + +static int pop3driver_cached_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg_info; + int r; + + msg_info = mailmessage_new(); + if (msg_info == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_init(msg_info, session, pop3_cached_message_driver, num, 0); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg_info); + return r; + } + + * result = msg_info; + + return MAIL_NO_ERROR; +} + +static int pop3driver_cached_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result) +{ + mailpop3 * pop3; + struct mailpop3_msg_info * msg_info; + int found; + unsigned int i; + + if (uid == NULL) + return MAIL_ERROR_INVAL; + + pop3 = get_pop3_session(session); + + found = 0; + + /* iterate all messages and look for uid */ + for(i = 0 ; i < carray_count(pop3->pop3_msg_tab) ; i++) { + msg_info = carray_get(pop3->pop3_msg_tab, i); + + if (msg_info == NULL) + continue; + + if (msg_info->msg_deleted) + continue; + + /* uid found, stop looking */ + if (strcmp(msg_info->msg_uidl, uid) == 0) { + found = 1; + break; + } + } + + if (!found) + return MAIL_ERROR_MSG_NOT_FOUND; + + return pop3driver_cached_get_message(session, msg_info->msg_index, result); +} + +static int pop3driver_cached_login_sasl(mailsession * session, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ + return mailsession_login_sasl(get_ancestor(session), auth_type, + server_fqdn, + local_ip_port, + remote_ip_port, + login, auth_name, + password, realm); +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_cached.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_cached.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_cached.h,v 1.15 2004/11/21 21:53:34 hoa Exp $ + */ + +#ifndef POP3DRIVER_CACHED_H + +#define POP3DRIVER_CACHED_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/pop3driver_types.h> + +extern mailsession_driver * pop3_cached_session_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,384 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_cached_message.c,v 1.20 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "pop3driver_cached_message.h" + +#include <string.h> +#include <stdlib.h> + +#include "mail_cache_db.h" + +#include "mailmessage.h" +#include "mailmessage_tools.h" +#include "pop3driver.h" +#include "pop3driver_tools.h" +#include "pop3driver_cached.h" +#include "pop3driver_message.h" +#include "generic_cache.h" + +static int pop3_prefetch(mailmessage * msg_info); + +static void pop3_prefetch_free(struct generic_message_t * msg); + +static int pop3_initialize(mailmessage * msg_info); + +static void pop3_flush(mailmessage * msg_info); + +static void pop3_check(mailmessage * msg_info); + +static int pop3_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int pop3_fetch_size(mailmessage * msg_info, + size_t * result); + +static int pop3_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +static void pop3_uninitialize(mailmessage * msg_info); + +static mailmessage_driver local_pop3_cached_message_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* msg_name */ "pop3-cached", + + /* msg_initialize */ pop3_initialize, + /* msg_uninitialize */ pop3_uninitialize, + + /* msg_flush */ pop3_flush, + /* msg_check */ pop3_check, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ pop3_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ pop3_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ pop3_get_flags, +#else + .msg_name = "pop3-cached", + + .msg_initialize = pop3_initialize, + .msg_uninitialize = pop3_uninitialize, + + .msg_flush = pop3_flush, + .msg_check = pop3_check, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = pop3_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = pop3_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = pop3_get_flags, +#endif +}; + +mailmessage_driver * pop3_cached_message_driver = +&local_pop3_cached_message_driver; + + +static inline struct pop3_cached_session_state_data * +get_cached_session_data(mailmessage * msg) +{ + return msg->msg_session->sess_data; +} + +static inline mailsession * get_ancestor_session(mailmessage * msg) +{ + return get_cached_session_data(msg)->pop3_ancestor; +} + +static inline struct pop3_session_state_data * +get_ancestor_session_data(mailmessage * msg) +{ + return get_ancestor_session(msg)->sess_data; +} + +static inline mailpop3 * get_pop3_session(mailmessage * msg) +{ + return get_ancestor_session_data(msg)->pop3_session; +} + + +static int pop3_prefetch(mailmessage * msg_info) +{ + char * msg_content; + size_t msg_length; + struct generic_message_t * msg; + int r; + struct pop3_cached_session_state_data * cached_data; + char filename[PATH_MAX]; + + /* we try the cached message */ + + cached_data = get_cached_session_data(msg_info); + + snprintf(filename, PATH_MAX, "%s/%s", + cached_data->pop3_cache_directory, msg_info->msg_uid); + + r = generic_cache_read(filename, &msg_content, &msg_length); + if (r == MAIL_NO_ERROR) { + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; + } + + /* we get the message through the network */ + + r = pop3driver_retr(get_ancestor_session(msg_info), msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + /* we write the message cache */ + + generic_cache_store(filename, msg_content, msg_length); + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void pop3_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int pop3_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + struct mailpop3_msg_info * info; + mailpop3 * pop3; + + pop3 = get_pop3_session(msg_info); + + r = mailpop3_get_msg_info(pop3, msg_info->msg_index, &info); + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + uid = strdup(info->msg_uidl); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = pop3_prefetch; + msg->msg_prefetch_free = pop3_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + +static void pop3_uninitialize(mailmessage * msg_info) +{ + mailmessage_generic_uninitialize(msg_info); +} + +#define FLAGS_NAME "flags.db" + +static void pop3_flush(mailmessage * msg_info) +{ + mailmessage_generic_flush(msg_info); +} + +static void pop3_check(mailmessage * msg_info) +{ + int r; + + if (msg_info->msg_flags != NULL) { + r = mail_flags_store_set(get_cached_session_data(msg_info)->pop3_flags_store, + msg_info); + } +} + + +static int pop3_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + char * headers; + size_t headers_length; + int r; + struct pop3_cached_session_state_data * cached_data; + char filename[PATH_MAX]; + + msg = msg_info->msg_data; + + if (msg->msg_message != NULL) + return mailmessage_generic_fetch_header(msg_info, + result, result_len); + + /* we try the cached message */ + + cached_data = get_cached_session_data(msg_info); + + snprintf(filename, PATH_MAX, "%s/%s-header", + cached_data->pop3_cache_directory, msg_info->msg_uid); + + r = generic_cache_read(filename, &headers, &headers_length); + if (r == MAIL_NO_ERROR) { + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; + } + + /* we get the message trough the network */ + + r = pop3driver_header(get_ancestor_session(msg_info), msg_info->msg_index, + &headers, &headers_length); + if (r != MAIL_NO_ERROR) + return r; + + generic_cache_store(filename, headers, headers_length); + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +static int pop3_fetch_size(mailmessage * msg_info, + size_t * result) +{ + return pop3driver_size(get_ancestor_session(msg_info), + msg_info->msg_index, result); +} + +static int pop3_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + int r; + struct mail_flags * flags; + struct mail_cache_db * cache_db_flags; + char filename_flags[PATH_MAX]; + int res; + struct pop3_cached_session_state_data * cached_data; + MMAPString * mmapstr; + + if (msg_info->msg_flags != NULL) { + * result = msg_info->msg_flags; + + return MAIL_NO_ERROR; + } + + cached_data = get_cached_session_data(msg_info); + + flags = mail_flags_store_get(cached_data->pop3_flags_store, + msg_info->msg_index); + + if (flags == NULL) { + snprintf(filename_flags, PATH_MAX, "%s/%s", + cached_data->pop3_flags_directory, FLAGS_NAME); + + r = mail_cache_db_open_lock(filename_flags, &cache_db_flags); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_db_flags; + } + + r = pop3driver_get_cached_flags(cache_db_flags, mmapstr, + msg_info->msg_session, msg_info->msg_index, &flags); + if (r != MAIL_NO_ERROR) { + flags = mail_flags_new_empty(); + if (flags == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mmapstr; + } + } + + mmap_string_free(mmapstr); + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + } + + msg_info->msg_flags = flags; + + * result = flags; + + return MAIL_NO_ERROR; + + free_mmapstr: + mmap_string_free(mmapstr); + close_db_flags: + mail_cache_db_close_unlock(filename_flags, cache_db_flags); + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_cached_message.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_cached_message.h,v 1.6 2004/11/21 21:53:34 hoa Exp $ + */ + +#ifndef POP3DRIVER_CACHED_MESSAGE_H + +#define POP3DRIVER_CACHED_MESSAGE_H + +#include <libetpan/pop3driver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * pop3_cached_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_message.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_message.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,222 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_message.c,v 1.14 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "pop3driver_message.h" + +#include "mailmessage_tools.h" +#include "pop3driver_tools.h" +#include "pop3driver.h" +#include "mailpop3.h" +#include <stdlib.h> +#include <string.h> + +static int pop3_prefetch(mailmessage * msg_info); + +static void pop3_prefetch_free(struct generic_message_t * msg); + +static int pop3_initialize(mailmessage * msg_info); + +static int pop3_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +static int pop3_fetch_size(mailmessage * msg_info, + size_t * result); + +static mailmessage_driver local_pop3_message_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* msg_name */ "pop3", + + /* msg_initialize */ pop3_initialize, + /* msg_uninitialize */ mailmessage_generic_uninitialize, + + /* msg_flush */ mailmessage_generic_flush, + /* msg_check */ NULL, + + /* msg_fetch_result_free */ mailmessage_generic_fetch_result_free, + + /* msg_fetch */ mailmessage_generic_fetch, + /* msg_fetch_header */ pop3_fetch_header, + /* msg_fetch_body */ mailmessage_generic_fetch_body, + /* msg_fetch_size */ pop3_fetch_size, + /* msg_get_bodystructure */ mailmessage_generic_get_bodystructure, + /* msg_fetch_section */ mailmessage_generic_fetch_section, + /* msg_fetch_section_header */ mailmessage_generic_fetch_section_header, + /* msg_fetch_section_mime */ mailmessage_generic_fetch_section_mime, + /* msg_fetch_section_body */ mailmessage_generic_fetch_section_body, + /* msg_fetch_envelope */ mailmessage_generic_fetch_envelope, + + /* msg_get_flags */ NULL, +#else + .msg_name = "pop3", + + .msg_initialize = pop3_initialize, + .msg_uninitialize = mailmessage_generic_uninitialize, + + .msg_flush = mailmessage_generic_flush, + .msg_check = NULL, + + .msg_fetch_result_free = mailmessage_generic_fetch_result_free, + + .msg_fetch = mailmessage_generic_fetch, + .msg_fetch_header = pop3_fetch_header, + .msg_fetch_body = mailmessage_generic_fetch_body, + .msg_fetch_size = pop3_fetch_size, + .msg_get_bodystructure = mailmessage_generic_get_bodystructure, + .msg_fetch_section = mailmessage_generic_fetch_section, + .msg_fetch_section_header = mailmessage_generic_fetch_section_header, + .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime, + .msg_fetch_section_body = mailmessage_generic_fetch_section_body, + .msg_fetch_envelope = mailmessage_generic_fetch_envelope, + + .msg_get_flags = NULL, +#endif +}; + +mailmessage_driver * pop3_message_driver = &local_pop3_message_driver; + +static inline struct pop3_session_state_data * +get_data(mailsession * session) +{ + return session->sess_data; +} + + +static mailpop3 * get_pop3_session(mailsession * session) +{ + return get_data(session)->pop3_session; +} + + +static int pop3_prefetch(mailmessage * msg_info) +{ + char * msg_content; + size_t msg_length; + struct generic_message_t * msg; + int r; + + r = pop3driver_retr(msg_info->msg_session, msg_info->msg_index, + &msg_content, &msg_length); + if (r != MAIL_NO_ERROR) + return r; + + msg = msg_info->msg_data; + + msg->msg_message = msg_content; + msg->msg_length = msg_length; + + return MAIL_NO_ERROR; +} + +static void pop3_prefetch_free(struct generic_message_t * msg) +{ + if (msg->msg_message != NULL) { + mmap_string_unref(msg->msg_message); + msg->msg_message = NULL; + } +} + +static int pop3_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + char * uid; + struct mailpop3_msg_info * info; + mailpop3 * pop3; + + pop3 = get_pop3_session(msg_info->msg_session); + + r = mailpop3_get_msg_info(pop3, msg_info->msg_index, &info); + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + uid = strdup(info->msg_uidl); + if (uid == NULL) + return MAIL_ERROR_MEMORY; + + r = mailmessage_generic_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + free(uid); + return r; + } + + msg = msg_info->msg_data; + msg->msg_prefetch = pop3_prefetch; + msg->msg_prefetch_free = pop3_prefetch_free; + msg_info->msg_uid = uid; + + return MAIL_NO_ERROR; +} + + +static int pop3_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + struct generic_message_t * msg; + char * headers; + size_t headers_length; + int r; + + msg = msg_info->msg_data; + + if (msg->msg_message != NULL) + return mailmessage_generic_fetch_header(msg_info, + result, result_len); + + r = pop3driver_header(msg_info->msg_session, msg_info->msg_index, + &headers, &headers_length); + if (r != MAIL_NO_ERROR) + return r; + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +static int pop3_fetch_size(mailmessage * msg_info, + size_t * result) +{ + return pop3driver_size(msg_info->msg_session, msg_info->msg_index, result); +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_message.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_message.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_message.h,v 1.6 2004/11/21 21:53:34 hoa Exp $ + */ + +#ifndef POP3DRIVER_MESSAGE_H + +#define POP3DRIVER_MESSAGE_H + +#include <libetpan/pop3driver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern mailmessage_driver * pop3_message_driver; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_tools.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_tools.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,350 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_tools.c,v 1.14 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "pop3driver_tools.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#include "maildriver_types.h" +#include "mailpop3.h" +#include "pop3driver.h" +#include "pop3driver_cached.h" +#include "generic_cache.h" +#include "imfcache.h" +#include "mailmessage.h" +#include "mail_cache_db.h" + +int pop3driver_pop3_error_to_mail_error(int error) +{ + switch (error) { + case MAILPOP3_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILPOP3_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + + case MAILPOP3_ERROR_UNAUTHORIZED: + return MAIL_ERROR_CONNECT; + + case MAILPOP3_ERROR_STREAM: + return MAIL_ERROR_STREAM; + + case MAILPOP3_ERROR_DENIED: + return MAIL_ERROR_CONNECT; + + case MAILPOP3_ERROR_BAD_USER: + case MAILPOP3_ERROR_BAD_PASSWORD: + return MAIL_ERROR_LOGIN; + + case MAILPOP3_ERROR_CANT_LIST: + return MAIL_ERROR_LIST; + + case MAILPOP3_ERROR_NO_SUCH_MESSAGE: + return MAIL_ERROR_MSG_NOT_FOUND; + + case MAILPOP3_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILPOP3_ERROR_CONNECTION_REFUSED: + return MAIL_ERROR_CONNECT; + + case MAILPOP3_ERROR_APOP_NOT_SUPPORTED: + return MAIL_ERROR_NO_APOP; + + case MAILPOP3_ERROR_CAPA_NOT_SUPPORTED: + return MAIL_ERROR_CAPABILITY; + + case MAILPOP3_ERROR_STLS_NOT_SUPPORTED: + return MAIL_ERROR_NO_TLS; + + default: + return MAIL_ERROR_INVAL; + } +}; + +static inline struct pop3_session_state_data * +session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailpop3 * session_get_pop3_session(mailsession * session) +{ + return session_get_data(session)->pop3_session; +} + +static inline struct pop3_cached_session_state_data * +cached_session_get_data(mailsession * session) +{ + return session->sess_data; +} + +static inline mailsession * +cached_session_get_ancestor(mailsession * session) +{ + return cached_session_get_data(session)->pop3_ancestor; +} + +static inline struct pop3_session_state_data * +cached_session_get_ancestor_data(mailsession * session) +{ + return session_get_data(cached_session_get_ancestor(session)); +} + +static inline mailpop3 * +cached_session_get_pop3_session(mailsession * session) +{ + return session_get_pop3_session(cached_session_get_ancestor(session)); +} + + +int pop3driver_retr(mailsession * session, uint32_t index, + char ** result, size_t * result_len) +{ + char * msg_content; + size_t msg_length; + int r; + + r = mailpop3_retr(session_get_pop3_session(session), index, + &msg_content, &msg_length); + + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + * result = msg_content; + * result_len = msg_length; + + return MAIL_NO_ERROR; +} + +int pop3driver_header(mailsession * session, uint32_t index, + char ** result, + size_t * result_len) +{ + char * headers; + size_t headers_length; + int r; + + r = mailpop3_header(session_get_pop3_session(session), + index, &headers, &headers_length); + + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + * result = headers; + * result_len = headers_length; + + return MAIL_NO_ERROR; +} + +int pop3driver_size(mailsession * session, uint32_t index, + size_t * result) +{ + mailpop3 * pop3; + carray * msg_tab; + struct mailpop3_msg_info * info; + int r; + + pop3 = session_get_pop3_session(session); + + mailpop3_list(pop3, &msg_tab); + + r = mailpop3_get_msg_info(pop3, index, &info); + switch (r) { + case MAILPOP3_NO_ERROR: + break; + default: + return pop3driver_pop3_error_to_mail_error(r); + } + + * result = info->msg_size; + + return MAIL_NO_ERROR; +} + +int +pop3driver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result) +{ + int r; + char keyname[PATH_MAX]; + struct mail_flags * flags; + int res; + struct mailpop3_msg_info * info; + + r = mailpop3_get_msg_info(cached_session_get_pop3_session(session), + num, &info); + switch (r) { + case MAILPOP3_ERROR_BAD_STATE: + return MAIL_ERROR_BAD_STATE; + case MAILPOP3_ERROR_NO_SUCH_MESSAGE: + return MAIL_ERROR_MSG_NOT_FOUND; + case MAILPOP3_NO_ERROR: + break; + default: + return MAIL_ERROR_FETCH; + } + + snprintf(keyname, PATH_MAX, "%s-flags", info->msg_uidl); + + r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int +pop3driver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags) +{ + int r; + char keyname[PATH_MAX]; + int res; + + snprintf(keyname, PATH_MAX, "%s-flags", uid); + + r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +int pop3_get_messages_list(mailpop3 * pop3, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result) +{ + carray * msg_tab; + carray * tab; + struct mailmessage_list * env_list; + unsigned int i; + int res; + int r; + + mailpop3_list(pop3, &msg_tab); + + tab = carray_new(128); + if (tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * pop3_info; + mailmessage * msg; + + pop3_info = carray_get(msg_tab, i); + + if (pop3_info == NULL) + continue; + + if (pop3_info->msg_deleted) + continue; + + msg = mailmessage_new(); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = mailmessage_init(msg, session, driver, + (uint32_t) pop3_info->msg_index, pop3_info->msg_size); + if (r != MAIL_NO_ERROR) { + mailmessage_free(msg); + res = r; + goto free_list; + } + + r = carray_add(tab, msg, NULL); + if (r < 0) { + mailmessage_free(msg); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + env_list = mailmessage_list_new(/*list*/ tab); + if (env_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = env_list; + + return MAIL_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(tab) ; i ++) + mailmessage_free(carray_get(tab, i)); + carray_free(tab); + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_tools.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_tools.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,82 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_tools.h,v 1.10 2004/11/21 21:53:34 hoa Exp $ + */ + +#ifndef POP3DRIVER_TOOLS_H + +#define POP3DRIVER_TOOLS_H + +#include "mail_cache_db_types.h" +#include "pop3driver_types.h" +#include "mailpop3.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int pop3driver_pop3_error_to_mail_error(int error); + +int pop3driver_retr(mailsession * session, uint32_t index, + char ** result, size_t * result_len); + +int pop3driver_header(mailsession * session, uint32_t index, + char ** result, + size_t * result_len); + +int pop3driver_size(mailsession * session, uint32_t index, + size_t * result); + +int +pop3driver_get_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + mailsession * session, + uint32_t num, + struct mail_flags ** result); + +int +pop3driver_write_cached_flags(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * uid, + struct mail_flags * flags); + +int pop3_get_messages_list(mailpop3 * pop3, + mailsession * session, + mailmessage_driver * driver, + struct mailmessage_list ** result); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3driver_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,165 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3driver_types.h,v 1.9 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef POP3DRIVER_TYPES_H + +#define POP3DRIVER_TYPES_H + +#include <libetpan/libetpan-config.h> + +#include <libetpan/maildriver_types.h> +#include <libetpan/mailpop3.h> +#include <libetpan/maildriver_types.h> +#include <libetpan/chash.h> +#include <libetpan/mailstorage_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* POP3 driver for session */ + +enum { + POP3DRIVER_SET_AUTH_TYPE = 1 +}; + +enum { + POP3DRIVER_AUTH_TYPE_PLAIN = 0, + POP3DRIVER_AUTH_TYPE_APOP, + POP3DRIVER_AUTH_TYPE_TRY_APOP +}; + +struct pop3_session_state_data { + int pop3_auth_type; + mailpop3 * pop3_session; +}; + +/* cached POP3 driver for session */ + +enum { + /* the mapping of the parameters should be the same as for pop3 */ + POP3DRIVER_CACHED_SET_AUTH_TYPE = 1, + /* cache specific */ + POP3DRIVER_CACHED_SET_CACHE_DIRECTORY, + POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY +}; + +struct pop3_cached_session_state_data { + mailsession * pop3_ancestor; + char pop3_cache_directory[PATH_MAX]; + char pop3_flags_directory[PATH_MAX]; + chash * pop3_flags_hash; + carray * pop3_flags_array; + struct mail_flags_store * pop3_flags_store; +}; + +/* pop3 storage */ + +/* + pop3_mailstorage is the state data specific to the POP3 storage. + + - servername this is the name of the POP3 server + + - port is the port to connect to, on the server. + you give 0 to use the default port. + + - connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS or CONNECTION_TYPE_TLS. + + - auth_type is the authenticate mechanism to use. + The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP + or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented. + + - login is the login of the POP3 account. + + - password is the password of the POP3 account. + + - cached if this value is != 0, a persistant cache will be + stored on local system. + + - cache_directory is the location of the cache. + + - flags_directory is the location of the flags. +*/ + +struct pop3_mailstorage { + char * pop3_servername; + uint16_t pop3_port; + char * pop3_command; + int pop3_connection_type; + + int pop3_auth_type; + char * pop3_login; /* deprecated */ + char * pop3_password; /* deprecated */ + + int pop3_cached; + char * pop3_cache_directory; + char * pop3_flags_directory; + + struct { + int sasl_enabled; + char * sasl_auth_type; + char * sasl_server_fqdn; + char * sasl_local_ip_port; + char * sasl_remote_ip_port; + char * sasl_login; + char * sasl_auth_name; + char * sasl_password; + char * sasl_realm; + } pop3_sasl; +}; + +/* this is the type of POP3 authentication */ + +enum { + POP3_AUTH_TYPE_PLAIN, /* plain text authentication */ + POP3_AUTH_TYPE_APOP, /* APOP authentication */ + POP3_AUTH_TYPE_TRY_APOP, /* first, try APOP, if it fails, + try plain text */ + POP3_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */ + POP3_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */ + POP3_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */ + POP3_AUTH_TYPE_SASL_PLAIN, /* SASL plain */ + POP3_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */ + POP3_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */ + POP3_AUTH_TYPE_SASL_DIGEST_MD5 /* SASL digest MD5 */ +}; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3storage.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3storage.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,414 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3storage.c,v 1.17 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "pop3storage.h" + +#include <stdlib.h> +#include <string.h> + +#include "mail.h" +#include "mailstorage_tools.h" +#include "maildriver.h" + +/* pop3 storage */ + +#define POP3_DEFAULT_PORT 110 +#define POP3S_DEFAULT_PORT 995 + +static int pop3_mailstorage_connect(struct mailstorage * storage); +static int pop3_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result); +static void pop3_mailstorage_uninitialize(struct mailstorage * storage); + +static mailstorage_driver pop3_mailstorage_driver = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* sto_name */ "pop3", + /* sto_connect */ pop3_mailstorage_connect, + /* sto_get_folder_session */ pop3_mailstorage_get_folder_session, + /* sto_uninitialize */ pop3_mailstorage_uninitialize, +#else + .sto_name = "pop3", + .sto_connect = pop3_mailstorage_connect, + .sto_get_folder_session = pop3_mailstorage_get_folder_session, + .sto_uninitialize = pop3_mailstorage_uninitialize, +#endif +}; + +LIBETPAN_EXPORT +int pop3_mailstorage_init(struct mailstorage * storage, + const char * pop3_servername, uint16_t pop3_port, + const char * pop3_command, + int pop3_connection_type, int pop3_auth_type, + const char * pop3_login, const char * pop3_password, + int pop3_cached, const char * pop3_cache_directory, const char * pop3_flags_directory) +{ + struct pop3_mailstorage * pop3_storage; + int r; + + r = pop3_mailstorage_init_sasl(storage, + pop3_servername, pop3_port, + pop3_command, + pop3_connection_type, + NULL, + NULL, + NULL, NULL, + pop3_login, pop3_login, + pop3_password, NULL, + pop3_cached, pop3_cache_directory, + pop3_flags_directory); + + if (r == MAIL_NO_ERROR) { + pop3_storage = storage->sto_data; + pop3_storage->pop3_auth_type = pop3_auth_type; + pop3_storage->pop3_login = pop3_storage->pop3_sasl.sasl_login; + pop3_storage->pop3_password = pop3_storage->pop3_sasl.sasl_password; + } + + return r; +} + +LIBETPAN_EXPORT +int pop3_mailstorage_init_sasl(struct mailstorage * storage, + const char * pop3_servername, uint16_t pop3_port, + const char * pop3_command, + int pop3_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int pop3_cached, const char * pop3_cache_directory, + const char * pop3_flags_directory) +{ + struct pop3_mailstorage * pop3_storage; + + pop3_storage = malloc(sizeof(* pop3_storage)); + if (pop3_storage == NULL) + goto err; + + pop3_storage->pop3_servername = strdup(pop3_servername); + if (pop3_storage->pop3_servername == NULL) + goto free; + + pop3_storage->pop3_connection_type = pop3_connection_type; + + if (pop3_port == 0) { + switch (pop3_connection_type) { + case CONNECTION_TYPE_PLAIN: + case CONNECTION_TYPE_TRY_STARTTLS: + case CONNECTION_TYPE_STARTTLS: + case CONNECTION_TYPE_COMMAND: + case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: + case CONNECTION_TYPE_COMMAND_STARTTLS: + pop3_port = POP3_DEFAULT_PORT; + break; + + case CONNECTION_TYPE_TLS: + case CONNECTION_TYPE_COMMAND_TLS: + pop3_port = POP3S_DEFAULT_PORT; + break; + } + } + + pop3_storage->pop3_port = pop3_port; + + if (pop3_command != NULL) { + pop3_storage->pop3_command = strdup(pop3_command); + if (pop3_storage->pop3_command == NULL) + goto free_servername; + } + else + pop3_storage->pop3_command = NULL; + + pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_PLAIN; + + pop3_storage->pop3_sasl.sasl_enabled = (auth_type != NULL); + + if (auth_type != NULL) { + pop3_storage->pop3_sasl.sasl_auth_type = strdup(auth_type); + if (pop3_storage->pop3_sasl.sasl_auth_type == NULL) + goto free_command; + } + else + pop3_storage->pop3_sasl.sasl_auth_type = NULL; + + if (server_fqdn != NULL) { + pop3_storage->pop3_sasl.sasl_server_fqdn = strdup(server_fqdn); + if (pop3_storage->pop3_sasl.sasl_server_fqdn == NULL) + goto free_auth_type; + } + else + pop3_storage->pop3_sasl.sasl_server_fqdn = NULL; + + if (local_ip_port != NULL) { + pop3_storage->pop3_sasl.sasl_local_ip_port = strdup(local_ip_port); + if (pop3_storage->pop3_sasl.sasl_local_ip_port == NULL) + goto free_server_fqdn; + } + else + pop3_storage->pop3_sasl.sasl_local_ip_port = NULL; + + if (remote_ip_port != NULL) { + pop3_storage->pop3_sasl.sasl_remote_ip_port = strdup(remote_ip_port); + if (pop3_storage->pop3_sasl.sasl_remote_ip_port == NULL) + goto free_local_ip_port; + } + else + pop3_storage->pop3_sasl.sasl_remote_ip_port = NULL; + + if (login != NULL) { + pop3_storage->pop3_sasl.sasl_login = strdup(login); + if (pop3_storage->pop3_sasl.sasl_login == NULL) + goto free_remote_ip_port; + } + else + pop3_storage->pop3_sasl.sasl_login = NULL; + + if (auth_name != NULL) { + pop3_storage->pop3_sasl.sasl_auth_name = strdup(auth_name); + if (pop3_storage->pop3_sasl.sasl_auth_name == NULL) + goto free_login; + } + else + pop3_storage->pop3_sasl.sasl_auth_name = NULL; + + if (password != NULL) { + pop3_storage->pop3_sasl.sasl_password = strdup(password); + if (pop3_storage->pop3_sasl.sasl_password == NULL) + goto free_auth_name; + } + else + pop3_storage->pop3_sasl.sasl_password = NULL; + + if (realm != NULL) { + pop3_storage->pop3_sasl.sasl_realm = strdup(realm); + if (pop3_storage->pop3_sasl.sasl_realm == NULL) + goto free_password; + } + else + pop3_storage->pop3_sasl.sasl_realm = NULL; + + pop3_storage->pop3_cached = pop3_cached; + + if (pop3_cached && (pop3_cache_directory != NULL) && + (pop3_flags_directory != NULL)) { + pop3_storage->pop3_cache_directory = strdup(pop3_cache_directory); + if (pop3_storage->pop3_cache_directory == NULL) + goto free_realm; + pop3_storage->pop3_flags_directory = strdup(pop3_flags_directory); + if (pop3_storage->pop3_flags_directory == NULL) + goto free_cache_directory; + } + else { + pop3_storage->pop3_cached = FALSE; + pop3_storage->pop3_cache_directory = NULL; + pop3_storage->pop3_flags_directory = NULL; + } + + storage->sto_data = pop3_storage; + storage->sto_driver = &pop3_mailstorage_driver; + + return MAIL_NO_ERROR; + + free_cache_directory: + free(pop3_storage->pop3_cache_directory); + free_realm: + free(pop3_storage->pop3_sasl.sasl_realm); + free_password: + free(pop3_storage->pop3_sasl.sasl_password); + free_auth_name: + free(pop3_storage->pop3_sasl.sasl_auth_name); + free_login: + free(pop3_storage->pop3_sasl.sasl_login); + free_remote_ip_port: + free(pop3_storage->pop3_sasl.sasl_remote_ip_port); + free_local_ip_port: + free(pop3_storage->pop3_sasl.sasl_local_ip_port); + free_server_fqdn: + free(pop3_storage->pop3_sasl.sasl_server_fqdn); + free_auth_type: + free(pop3_storage->pop3_sasl.sasl_auth_type); + free_command: + if (pop3_storage->pop3_command != NULL) + free(pop3_storage->pop3_command); + free_servername: + if (pop3_storage->pop3_servername != NULL) + free(pop3_storage->pop3_servername); + free: + free(pop3_storage); + err: + return MAIL_ERROR_MEMORY; +} + +static void pop3_mailstorage_uninitialize(struct mailstorage * storage) +{ + struct pop3_mailstorage * pop3_storage; + + pop3_storage = storage->sto_data; + + if (pop3_storage->pop3_flags_directory != NULL) + free(pop3_storage->pop3_flags_directory); + if (pop3_storage->pop3_cache_directory != NULL) + free(pop3_storage->pop3_cache_directory); + + free(pop3_storage->pop3_sasl.sasl_realm); + free(pop3_storage->pop3_sasl.sasl_password); + free(pop3_storage->pop3_sasl.sasl_auth_name); + free(pop3_storage->pop3_sasl.sasl_login); + free(pop3_storage->pop3_sasl.sasl_remote_ip_port); + free(pop3_storage->pop3_sasl.sasl_local_ip_port); + free(pop3_storage->pop3_sasl.sasl_server_fqdn); + free(pop3_storage->pop3_sasl.sasl_auth_type); + + if (pop3_storage->pop3_command != NULL) + free(pop3_storage->pop3_command); + free(pop3_storage->pop3_servername); + free(pop3_storage); + + storage->sto_data = pop3_storage; +} + +static int pop3_mailstorage_connect(struct mailstorage * storage) +{ + struct pop3_mailstorage * pop3_storage; + mailsession_driver * driver; + int r; + int res; + mailsession * session; + int auth_type; + + pop3_storage = storage->sto_data; + + if (pop3_storage->pop3_cached) + driver = pop3_cached_session_driver; + else + driver = pop3_session_driver; + + r = mailstorage_generic_connect(driver, + pop3_storage->pop3_servername, + pop3_storage->pop3_port, pop3_storage->pop3_command, + pop3_storage->pop3_connection_type, + POP3DRIVER_CACHED_SET_CACHE_DIRECTORY, + pop3_storage->pop3_cache_directory, + POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY, + pop3_storage->pop3_flags_directory, + &session); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto err; + } + + auth_type = -1; + switch (pop3_storage->pop3_auth_type) { + case POP3_AUTH_TYPE_PLAIN: + auth_type = POP3DRIVER_AUTH_TYPE_PLAIN; + break; + case POP3_AUTH_TYPE_APOP: + auth_type = POP3DRIVER_AUTH_TYPE_APOP; + break; + case POP3_AUTH_TYPE_TRY_APOP: + auth_type = POP3DRIVER_AUTH_TYPE_TRY_APOP; + break; + } + + if (auth_type != -1) { + mailsession_parameters(session, POP3DRIVER_SET_AUTH_TYPE, &auth_type); + } + + if (pop3_storage->pop3_sasl.sasl_enabled) { + r = mailstorage_generic_auth_sasl(session, r, + pop3_storage->pop3_sasl.sasl_auth_type, + pop3_storage->pop3_sasl.sasl_server_fqdn, + pop3_storage->pop3_sasl.sasl_local_ip_port, + pop3_storage->pop3_sasl.sasl_remote_ip_port, + pop3_storage->pop3_sasl.sasl_login, + pop3_storage->pop3_sasl.sasl_auth_name, + pop3_storage->pop3_sasl.sasl_password, + pop3_storage->pop3_sasl.sasl_realm); + } + else { + r = mailstorage_generic_auth(session, r, + pop3_storage->pop3_auth_type, + pop3_storage->pop3_sasl.sasl_login, + pop3_storage->pop3_sasl.sasl_password); + } + if (r != MAIL_NO_ERROR) { + if (pop3_storage->pop3_auth_type == POP3_AUTH_TYPE_TRY_APOP) { + /* try in clear authentication */ + mailsession_free(session); + + pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_PLAIN; + r = mailstorage_connect(storage); + if (r != MAIL_NO_ERROR) { + res = r; + return res; + } + pop3_storage->pop3_auth_type = POP3_AUTH_TYPE_TRY_APOP; + + return MAIL_NO_ERROR; + } + + res = r; + goto free; + } + + storage->sto_session = session; + + return MAIL_NO_ERROR; + + free: + mailsession_free(session); + err: + return res; +} + +static int pop3_mailstorage_get_folder_session(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + * result = storage->sto_session; + + return MAIL_NO_ERROR; +} + Added: freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3storage.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/implementation/pop3/pop3storage.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,110 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: pop3storage.h,v 1.11 2006/06/02 15:44:30 smarinier Exp $ + */ + +#ifndef POP3STORAGE_H + +#define POP3STORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/pop3driver_types.h> +#include <libetpan/pop3driver.h> +#include <libetpan/pop3driver_cached.h> + +/* + pop3_mailstorage_init is the constructor for a POP3 storage + + @param storage this is the storage to initialize. + + @param servername this is the name of the POP3 server + + @param port is the port to connect to, on the server. + you give 0 to use the default port. + + @param command the command used to connect to the server instead of + allowing normal TCP connections to be used. + + @param connection_type is the type of socket layer to use. + The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS, + CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS, + CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS, + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,. + + @param auth_type is the authenticate mechanism to use. + The value can be POP3_AUTH_TYPE_PLAIN, POP3_AUTH_TYPE_APOP + or POP3_AUTH_TYPE_TRY_APOP. Other values are not yet implemented. + + @param login is the login of the POP3 account. + + @param password is the password of the POP3 account. + + @param cached if this value is != 0, a persistant cache will be + stored on local system. + + @param cache_directory is the location of the cache + + @param flags_directory is the location of the flags +*/ + +LIBETPAN_EXPORT +int pop3_mailstorage_init(struct mailstorage * storage, + const char * pop3_servername, uint16_t pop3_port, + const char * pop3_command, + int pop3_connection_type, int pop3_auth_type, + const char * pop3_login, const char * pop3_password, + int pop3_cached, const char * pop3_cache_directory, + const char * pop3_flags_directory); + +LIBETPAN_EXPORT +int pop3_mailstorage_init_sasl(struct mailstorage * storage, + const char * pop3_servername, uint16_t pop3_port, + const char * pop3_command, + int pop3_connection_type, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm, + int pop3_cached, const char * pop3_cache_directory, + const char * pop3_flags_directory); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/interface/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/driver/interface/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,32 @@ +top_builddir = ../../.. + +HEADERS = \ + maildriver.h maildriver_types.h maildriver_types_helper.h \ + maildriver_errors.h \ + mailmessage.h mailmessage_types.h \ + mailstorage.h \ + mailstorage_types.h \ + mailfolder.h + + +SOURCES = \ + maildriver.c maildriver_types.c \ + maildriver_tools.c \ + mailmessage.c mailmessage_tools.c mailmessage_types.c \ + maildriver_types_helper.c \ + mailstorage.c \ + mailstorage_tools.c \ + mailfolder.c + + +TARGET = libinterface +INCLUDES = -I$(srcdir)/low-level/imf \ + -I$(srcdir)/low-level/mime \ + -I$(srcdir)/data-types \ + -I../tools + +#INCLUDES = -I../tools +#INCLUDES = -I../imf -I../tools -I../mime -I../imap -I../mbox -I../pop3 \ +# -I../nntp -I../mh -I../maildir -I../smtp + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,441 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver.c,v 1.28 2006/06/07 15:10:01 smarinier Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "maildriver.h" +#include <ctype.h> +#include <string.h> +#include <stdlib.h> + +/* *********************************************************************** */ +/* mail session */ + +LIBETPAN_EXPORT +mailsession * mailsession_new(mailsession_driver * sess_driver) +{ + mailsession * session; + int r; + + session = malloc(sizeof(* session)); + + session->sess_data = NULL; + + if (sess_driver->sess_initialize != NULL) { + r = sess_driver->sess_initialize(session); + if (r != MAIL_NO_ERROR) + goto free; + } + + session->sess_driver = sess_driver; + + return session; + + free: + free(session); + return NULL; +} + +LIBETPAN_EXPORT +void mailsession_free(mailsession * session) +{ + if (session->sess_driver->sess_uninitialize != NULL) + session->sess_driver->sess_uninitialize(session); + free(session); +} + +LIBETPAN_EXPORT +int mailsession_parameters(mailsession * session, + int id, void * value) +{ + if (session->sess_driver->sess_parameters == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_parameters(session, id, value); +} + +LIBETPAN_EXPORT +int mailsession_connect_stream(mailsession * session, mailstream * s) +{ + if (session->sess_driver->sess_connect_stream == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_connect_stream(session, s); +} + +LIBETPAN_EXPORT +int mailsession_connect_path(mailsession * session, const char * path) +{ + if (session->sess_driver->sess_connect_path == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_connect_path(session, path); +} + +LIBETPAN_EXPORT +int mailsession_starttls(mailsession * session) +{ + if (session->sess_driver->sess_starttls == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_starttls(session); +} + +LIBETPAN_EXPORT +int mailsession_login(mailsession * session, + const char * userid, const char * password) +{ + if (session->sess_driver->sess_login == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_login(session, userid, password); +} + +LIBETPAN_EXPORT +int mailsession_logout(mailsession * session) +{ + if (session->sess_driver->sess_logout == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_logout(session); +} + +LIBETPAN_EXPORT +int mailsession_noop(mailsession * session) +{ + if (session->sess_driver->sess_noop == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_noop(session); +} + +/* folders operations */ + +LIBETPAN_EXPORT +int mailsession_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result) +{ + if (session->sess_driver->sess_build_folder_name == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_build_folder_name(session, + mb, name, result); +} + +LIBETPAN_EXPORT +int mailsession_create_folder(mailsession * session, const char * mb) +{ + if (session->sess_driver->sess_create_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_create_folder(session, mb); +} + +LIBETPAN_EXPORT +int mailsession_delete_folder(mailsession * session, const char * mb) +{ + if (session->sess_driver->sess_delete_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_delete_folder(session, mb); +} + +LIBETPAN_EXPORT +int mailsession_rename_folder(mailsession * session, + const char * mb, const char * new_name) +{ + if (session->sess_driver->sess_rename_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_rename_folder(session, mb, new_name); +} + +LIBETPAN_EXPORT +int mailsession_check_folder(mailsession * session) +{ + if (session->sess_driver->sess_check_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_check_folder(session); +} + +LIBETPAN_EXPORT +int mailsession_examine_folder(mailsession * session, const char * mb) +{ + if (session->sess_driver->sess_examine_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_examine_folder(session, mb); +} + +LIBETPAN_EXPORT +int mailsession_select_folder(mailsession * session, const char * mb) +{ + if (session->sess_driver->sess_select_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_select_folder(session, mb); +} + +LIBETPAN_EXPORT +int mailsession_expunge_folder(mailsession * session) +{ + if (session->sess_driver->sess_expunge_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_expunge_folder(session); +} + +LIBETPAN_EXPORT +int mailsession_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + if (session->sess_driver->sess_status_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_status_folder(session, mb, + result_messages, result_recent, result_unseen); +} + +LIBETPAN_EXPORT +int mailsession_messages_number(mailsession * session, const char * mb, + uint32_t * result) +{ + if (session->sess_driver->sess_messages_number == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_messages_number(session, mb, result); +} + +LIBETPAN_EXPORT +int mailsession_recent_number(mailsession * session, const char * mb, + uint32_t * result) +{ + if (session->sess_driver->sess_recent_number == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_recent_number(session, mb, result); +} + +LIBETPAN_EXPORT +int mailsession_unseen_number(mailsession * session, const char * mb, + uint32_t * result) +{ + if (session->sess_driver->sess_unseen_number == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_unseen_number(session, mb, result); +} + +LIBETPAN_EXPORT +int mailsession_list_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + if (session->sess_driver->sess_list_folders == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_list_folders(session, mb, result); +} + +LIBETPAN_EXPORT +int mailsession_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result) +{ + if (session->sess_driver->sess_lsub_folders == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_lsub_folders(session, mb, result); +} + +LIBETPAN_EXPORT +int mailsession_subscribe_folder(mailsession * session, const char * mb) +{ + if (session->sess_driver->sess_subscribe_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_subscribe_folder(session, mb); +} + +LIBETPAN_EXPORT +int mailsession_unsubscribe_folder(mailsession * session, const char * mb) +{ + if (session->sess_driver->sess_unsubscribe_folder == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_unsubscribe_folder(session, mb); +} + +/* message */ + +LIBETPAN_EXPORT +int mailsession_append_message(mailsession * session, + const char * message, size_t size) +{ + if (session->sess_driver->sess_append_message == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_append_message(session, message, size); +} + +LIBETPAN_EXPORT +int mailsession_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags) +{ + if (session->sess_driver->sess_append_message_flags == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_append_message_flags(session, + message, size, flags); +} + +LIBETPAN_EXPORT +int mailsession_copy_message(mailsession * session, + uint32_t num, const char * mb) +{ + if (session->sess_driver->sess_copy_message == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_copy_message(session, num, mb); +} + +LIBETPAN_EXPORT +int mailsession_move_message(mailsession * session, + uint32_t num, const char * mb) +{ + if (session->sess_driver->sess_move_message == NULL) { + int r; + + if ((session->sess_driver->sess_copy_message == NULL) && + (session->sess_driver->sess_remove_message == NULL)) + return MAIL_ERROR_NOT_IMPLEMENTED; + + r = mailsession_copy_message(session, num, mb); + if (r != MAIL_NO_ERROR) + return r; + + r = mailsession_remove_message(session, num); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; + } + + return session->sess_driver->sess_move_message(session, num, mb); +} + +LIBETPAN_EXPORT +int mailsession_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + if (session->sess_driver->sess_get_envelopes_list == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_get_envelopes_list(session, env_list); +} + +LIBETPAN_EXPORT +int mailsession_get_messages_list(mailsession * session, + struct mailmessage_list ** result) +{ + if (session->sess_driver->sess_get_messages_list == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_get_messages_list(session, result); +} + +LIBETPAN_EXPORT +int mailsession_remove_message(mailsession * session, uint32_t num) +{ + if (session->sess_driver->sess_remove_message == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_remove_message(session, num); +} + +#if 0 +LIBETPAN_EXPORT +int mailsession_search_messages(mailsession * session, const char * charset, + struct mail_search_key * key, + struct mail_search_result ** result) +{ + if (session->sess_driver->sess_search_messages == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_search_messages(session, + charset, key, result); +} +#endif + +LIBETPAN_EXPORT +int mailsession_get_message(mailsession * session, + uint32_t num, mailmessage ** result) +{ + if (session->sess_driver->sess_get_message == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_get_message(session, num, result); +} + +LIBETPAN_EXPORT +int mailsession_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result) +{ + if (session->sess_driver->sess_get_message_by_uid == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_get_message_by_uid(session, uid, result); +} + +LIBETPAN_EXPORT +int mailsession_login_sasl(mailsession * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ + if (session->sess_driver->sess_login_sasl == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return session->sess_driver->sess_login_sasl(session, auth_type, + server_fqdn, + local_ip_port, + remote_ip_port, + login, auth_name, + password, realm); +} Added: freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,607 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver.h,v 1.34 2006/06/07 15:10:01 smarinier Exp $ + */ + +#ifndef MAILDRIVER_H + +#define MAILDRIVER_H + +#include <libetpan/maildriver_types.h> +#include <libetpan/maildriver_types_helper.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* mailsession */ + +/* + mailsession_new creates a new session, using the given driver + + @return the created session is returned +*/ + +LIBETPAN_EXPORT +mailsession * mailsession_new(mailsession_driver * sess_driver); + +/* + mailsession_free release the memory used by the session +*/ + +LIBETPAN_EXPORT +void mailsession_free(mailsession * session); + +/* + mailsession_parameters is used to make calls specific to the driver + + @param id is the command to send to the driver, + usually, commands can be found in the header of the driver + + @param value is the parameter of the specific call + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_parameters(mailsession * session, + int id, void * value); + +/* + There are drivers of two kinds : stream drivers (driver that connects + to servers through TCP or other means of connection) and file drivers + (driver that are based on filesystem) + + The following function can only be used by stream drivers. + mailsession_connect_stream connects a stream to the session + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_connect_stream(mailsession * session, mailstream * s); + +/* + The following function can only be used by file drivers. + mailsession_connect_path selects the main path of the session + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_connect_path(mailsession * session, const char * path); + +/* + NOTE: works only on stream drivers + + mailsession_starttls switches the current connection to TLS (secure layer) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_starttls(mailsession * session); + +/* + mailsession_login notifies the login and the password to authenticate + to the session + + @param userid the given string is only needed at this function call + (it will be duplicated if necessary) + @param password the given string is only needed at this function call + (it will be duplicated if necessary) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_login(mailsession * session, + const char * userid, const char * password); + +/* + NOTE: this function doesn't often work on filsystem drivers + + mailsession_logout deconnects the session and closes the stream. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_logout(mailsession * session); + +/* + mailsession_noop does no operation on the session, but it can be + used to poll for the status of the connection. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_noop(mailsession * session); + +/* + NOTE: driver's specific should be used + + mailsession_build_folder_name will return an allocated string with + that contains the complete path of the folder to create + + @param session the sesion + @param mb is the parent mailbox + @param name is the name of the folder to create + @param result the complete path of the folder to create will be + stored in (* result), this name have to be freed with free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_build_folder_name(mailsession * session, const char * mb, + const char * name, char ** result); + +/* + NOTE: driver's specific should be used + + mailsession_create_folder creates the folder that corresponds to the + given name + + @param session the session + @param mb is the name of the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_create_folder(mailsession * session, const char * mb); + + +/* + NOTE: driver's specific should be used + + mailsession_delete_folder deletes the folder that corresponds to the + given name + + @param session the session + @param mb is the name of the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_delete_folder(mailsession * session, const char * mb); + + +/* + mailsession_rename_folder changes the name of the folder + + @param session the session + @param mb is the name of the mailbox whose name has to be changed + @param new_name is the destination name (the parent + of the new folder folder can be other) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_rename_folder(mailsession * session, + const char * mb, const char * new_name); + +/* + mailsession_check_folder makes a checkpoint of the session + + @param session the session + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_check_folder(mailsession * session); + + +/* + NOTE: this function is not implemented in most drivers + + mailsession_examine_folder selects a mailbox as readonly + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_examine_folder(mailsession * session, const char * mb); + + +/* + mailsession_select_folder selects a mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_select_folder(mailsession * session, const char * mb); + + +/* + mailsession_expunge_folder deletes all messages marked \Deleted + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_expunge_folder(mailsession * session); + + +/* + mailsession_status_folder queries the status of the folder + (number of messages, number of recent messages, number of unseen messages) + + @param session the session + @param mb mailbox to query + @param result_messages the number of messages is stored + in (* result_messages) + @param result_recent the number of messages is stored + in (* result_recent) + @param result_unseen the number of messages is stored + in (* result_unseen) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_status_folder(mailsession * session, const char * mb, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + + +/* + mailsession_messages_number queries the number of messages in the folder + + @param session the session + @param mb mailbox to query + @param result the number of messages is stored in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_messages_number(mailsession * session, const char * mb, + uint32_t * result); + +/* + mailsession_recent_number queries the number of recent messages in the folder + + @param session the session + @param mb mailbox to query + @param result the number of recent messages is stored in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_recent_number(mailsession * session, + const char * mb, uint32_t * result); + +/* + mailsession_unseen_number queries the number of unseen messages in the folder + + @param session the session + @param mb mailbox to query + @param result the number of unseen messages is stored in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_unseen_number(mailsession * session, const char * mb, + uint32_t * result); + +/* + NOTE: driver's specific should be used + + mailsession_list_folders returns the list of all sub-mailboxes + of the given mailbox + + @param session the session + @param mb the mailbox + @param result list of mailboxes if stored in (* result), + this structure have to be freed with mail_list_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_list_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +/* + NOTE: driver's specific should be used + + mailsession_lsub_folders returns the list of subscribed + sub-mailboxes of the given mailbox + + @param session the session + @param mb the mailbox + @param result list of mailboxes if stored in (* result), + this structure have to be freed with mail_list_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_lsub_folders(mailsession * session, const char * mb, + struct mail_list ** result); + +/* + NOTE: driver's specific should be used + + mailsession_subscribe_folder subscribes to the given mailbox + + @param session the session + @param mb the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_subscribe_folder(mailsession * session, const char * mb); + +/* + NOTE: driver's specific should be used + + mailsession_unsubscribe_folder unsubscribes to the given mailbox + + @param session the session + @param mb the mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_unsubscribe_folder(mailsession * session, const char * mb); + +/* + mailsession_append_message adds a RFC 2822 message to the current + given mailbox + + @param session the session + @param message is a string that contains the RFC 2822 message + @param size this is the size of the message + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_append_message(mailsession * session, + const char * message, size_t size); + +LIBETPAN_EXPORT +int mailsession_append_message_flags(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + +/* + NOTE: some drivers does not implement this + + mailsession_copy_message copies a message whose number is given to + a given mailbox. The mailbox must be accessible from the same session. + + @param session the session + @param num the message number + @param mb the destination mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_copy_message(mailsession * session, + uint32_t num, const char * mb); + +/* + NOTE: some drivers does not implement this + + mailsession_move_message copies a message whose number is given to + a given mailbox. The mailbox must be accessible from the same session. + + @param session the session + @param num the message number + @param mb the destination mailbox + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_move_message(mailsession * session, + uint32_t num, const char * mb); + +/* + mailsession_get_messages_list returns the list of message numbers + of the current mailbox. + + @param session the session + @param result the list of message numbers will be stored in (* result), + this structure have to be freed with mailmessage_list_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_get_messages_list(mailsession * session, + struct mailmessage_list ** result); + +/* + mailsession_get_envelopes_list fills the parsed fields in the + mailmessage structures of the mailmessage_list. + + @param session the session + @param result this is the list of mailmessage structures + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_get_envelopes_list(mailsession * session, + struct mailmessage_list * result); + +/* + NOTE: some drivers does not implement this + + mailsession_remove_message removes the given message from the mailbox. + The message is permanently deleted. + + @param session the session + @param num is the message number + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_remove_message(mailsession * session, uint32_t num); + + +/* + NOTE: this function is not implemented in most drivers + + mailsession_search_message returns a list of message numbers that + corresponds to the given criteria. + + @param session the session + @param charset is the charset to use (it can be NULL) + @param key is the list of criteria + @param result the search result is stored in (* result), + this structure have to be freed with mail_search_result_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +#if 0 +LIBETPAN_EXPORT +int mailsession_search_messages(mailsession * session, const char * charset, + struct mail_search_key * key, + struct mail_search_result ** result); +#endif + +/* + mailsession_get_message returns a mailmessage structure that corresponds + to the given message number. + * WARNING * mailsession_get_message_by_uid() should be used instead. + + @param session the session + @param num the message number + @param result the allocated mailmessage structure will be stored + in (* result), this structure have to be freed with mailmessage_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_get_message(mailsession * session, + uint32_t num, mailmessage ** result); + +/* + mailsession_get_message_by_uid returns a mailmessage structure + that corresponds to the given message unique identifier. + This is currently implemented only for cached drivers. + * WARNING * That will deprecates the use of mailsession_get_message() + + @param session the session + @param uid the message unique identifier + @param result the allocated mailmessage structure will be stored + in (* result), this structure have to be freed with mailmessage_free() + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_get_message_by_uid(mailsession * session, + const char * uid, mailmessage ** result); + + +/* + mailsession_login notifies the SASL authentication information + to the session + + @param auth_type type of SASL authentication + @param server_fqdn server full qualified domain name + @param local_ip_port local IP:port (client) + @param remote_ip_port remote IP:port (server) + @param login login + @param auth_name authentication name + @param password password + @param realm realm + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +LIBETPAN_EXPORT +int mailsession_login_sasl(mailsession * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_errors.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_errors.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,102 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_errors.h,v 1.8 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MAILDRIVER_ERRORS_H + +#define MAILDRIVER_ERRORS_H + +enum { + MAIL_NO_ERROR = 0, + MAIL_NO_ERROR_AUTHENTICATED, + MAIL_NO_ERROR_NON_AUTHENTICATED, + MAIL_ERROR_NOT_IMPLEMENTED, + MAIL_ERROR_UNKNOWN, + MAIL_ERROR_CONNECT, + MAIL_ERROR_BAD_STATE, + MAIL_ERROR_FILE, + MAIL_ERROR_STREAM, + MAIL_ERROR_LOGIN, + MAIL_ERROR_CREATE, /* 10 */ + MAIL_ERROR_DELETE, + MAIL_ERROR_LOGOUT, + MAIL_ERROR_NOOP, + MAIL_ERROR_RENAME, + MAIL_ERROR_CHECK, + MAIL_ERROR_EXAMINE, + MAIL_ERROR_SELECT, + MAIL_ERROR_MEMORY, + MAIL_ERROR_STATUS, + MAIL_ERROR_SUBSCRIBE, /* 20 */ + MAIL_ERROR_UNSUBSCRIBE, + MAIL_ERROR_LIST, + MAIL_ERROR_LSUB, + MAIL_ERROR_APPEND, + MAIL_ERROR_COPY, + MAIL_ERROR_FETCH, + MAIL_ERROR_STORE, + MAIL_ERROR_SEARCH, + MAIL_ERROR_DISKSPACE, + MAIL_ERROR_MSG_NOT_FOUND, /* 30 */ + MAIL_ERROR_PARSE, + MAIL_ERROR_INVAL, + MAIL_ERROR_PART_NOT_FOUND, + MAIL_ERROR_REMOVE, + MAIL_ERROR_FOLDER_NOT_FOUND, + MAIL_ERROR_MOVE, + MAIL_ERROR_STARTTLS, + MAIL_ERROR_CACHE_MISS, + MAIL_ERROR_NO_TLS, + MAIL_ERROR_EXPUNGE, /* 40 */ + /* misc errors */ + MAIL_ERROR_MISC, + MAIL_ERROR_PROTOCOL, + MAIL_ERROR_CAPABILITY, + MAIL_ERROR_CLOSE, + MAIL_ERROR_FATAL, + MAIL_ERROR_READONLY, + MAIL_ERROR_NO_APOP, + MAIL_ERROR_COMMAND_NOT_SUPPORTED, + MAIL_ERROR_NO_PERMISSION, + MAIL_ERROR_PROGRAM_ERROR, /* 50 */ + MAIL_ERROR_SUBJECT_NOT_FOUND, + MAIL_ERROR_CHAR_ENCODING_FAILED, + MAIL_ERROR_SEND, + MAIL_ERROR_COMMAND, + MAIL_ERROR_SYSTEM, + MAIL_ERROR_UNABLE, + MAIL_ERROR_FOLDER +}; + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_tools.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_tools.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,848 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_tools.c,v 1.34 2006/06/07 15:10:01 smarinier Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "maildriver_tools.h" + +#include "libetpan-config.h" + +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#ifdef _MSC_VER +#include "win_etpan.h" +#else +# include <dirent.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include "maildriver.h" +#include "mailmessage.h" +#include "mailstream.h" +#include "mailmime.h" +#include "mail_cache_db.h" + +/* ********************************************************************* */ +/* tools */ + + +int +maildriver_generic_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list) +{ + int r; + unsigned i; +#if 0 + uint32_t j; + uint32_t last_msg; + + last_msg = 0; +#endif + +#if 0 + j = 0; + i = 0; + while (i < env_list->tab->len) { + mailmessage * msg; + uint32_t index; + + msg = carray_get(env_list->tab, i); + + index = msg->index; + + if (msg->fields == NULL) { + struct mailimf_fields * fields; + + r = mailmessage_fetch_envelope(msg, &fields); + if (r != MAIL_NO_ERROR) { + /* do nothing */ + } + else { + msg->fields = fields; + + carray_set(env_list->tab, j, msg); + + j ++; + last_msg = i + 1; + } + mailmessage_flush(msg); + } + else { + j ++; + last_msg = i + 1; + } + + i ++; + } + + for(i = last_msg ; i < env_list->tab->len ; i ++) { + mailmessage_free(carray_get(env_list->tab, i)); + carray_set(env_list->tab, i, NULL); + } + + r = carray_set_size(env_list->tab, j); + if (r < 0) + return MAIL_ERROR_MEMORY; +#endif + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + struct mailimf_fields * fields; + + r = mailmessage_fetch_envelope(msg, &fields); + if (r != MAIL_NO_ERROR) { + /* do nothing */ + } + else { + msg->msg_fields = fields; + } + mailmessage_flush(msg); + } + } + + return MAIL_NO_ERROR; +} + + +#if 0 +static int is_search_header_only(struct mail_search_key * key) +{ + clistiter * cur; + int result; + + switch (key->type) { + case MAIL_SEARCH_KEY_ANSWERED: + case MAIL_SEARCH_KEY_BCC: + case MAIL_SEARCH_KEY_BEFORE: + case MAIL_SEARCH_KEY_CC: + case MAIL_SEARCH_KEY_DELETED: + case MAIL_SEARCH_KEY_FLAGGED: + case MAIL_SEARCH_KEY_FROM: + case MAIL_SEARCH_KEY_NEW: + case MAIL_SEARCH_KEY_OLD: + case MAIL_SEARCH_KEY_ON: + case MAIL_SEARCH_KEY_RECENT: + case MAIL_SEARCH_KEY_SEEN: + case MAIL_SEARCH_KEY_SINCE: + case MAIL_SEARCH_KEY_SUBJECT: + case MAIL_SEARCH_KEY_TO: + case MAIL_SEARCH_KEY_UNANSWERED: + case MAIL_SEARCH_KEY_UNDELETED: + case MAIL_SEARCH_KEY_UNFLAGGED: + case MAIL_SEARCH_KEY_UNSEEN: + case MAIL_SEARCH_KEY_HEADER: + case MAIL_SEARCH_KEY_LARGER: + case MAIL_SEARCH_KEY_NOT: + case MAIL_SEARCH_KEY_SMALLER: + case MAIL_SEARCH_KEY_ALL: + return TRUE; + + case MAIL_SEARCH_KEY_BODY: + case MAIL_SEARCH_KEY_TEXT: + return FALSE; + + case MAIL_SEARCH_KEY_OR: + return (is_search_header_only(key->or1) && + is_search_header_only(key->or2)); + + case MAIL_SEARCH_KEY_MULTIPLE: + result = TRUE; + for (cur = clist_begin(key->multiple) ; cur != NULL ; + cur = clist_next(cur)) + result = result && is_search_header_only(clist_content(cur)); + return result; + + default: + return TRUE; + } +} + +static int match_header(struct mailimf_fields * fields, + char * name, char * value) +{ + clistiter * cur; + + for(cur = clist_begin(fields->list) ; cur != NULL ; + cur = clist_content(cur)) { + struct mailimf_field * field; + struct mailimf_optional_field * opt_field; + + field = clist_content(cur); + opt_field = field->optional_field; + if ((char) toupper((unsigned char) opt_field->name[0]) == + (char) toupper((unsigned char) name[0])) { + if (strcasecmp(opt_field->name, name) == 0) + if (strstr(opt_field->value, value) != NULL) + return TRUE; + } + } + return FALSE; +} + +static int comp_date(struct mailimf_fields * fields, + struct mailimf_date_time * ref_date) +{ + clistiter * cur; + struct mailimf_date_time * date; + int r; + + date = NULL; + for(cur = clist_begin(fields->list) ; cur != NULL ; + cur = clist_content(cur)) { + struct mailimf_field * field; + struct mailimf_optional_field * opt_field; + + field = clist_content(cur); + opt_field = field->optional_field; + if ((char) toupper((unsigned char) opt_field->name[0]) == 'D') { + if (strcasecmp(opt_field->name, "Date") == 0) { + size_t cur_token; + + cur_token = 0; + r = mailimf_date_time_parse(opt_field->value, strlen(opt_field->value), + &cur_token, &date); + if (r == MAILIMF_NO_ERROR) + break; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + break; + } + } + } + + if (date == NULL) + return 0; + + return mailimf_date_time_comp(date, ref_date); +} + +static int match_messages(char * message, + size_t size, + struct mailimf_fields * fields, + int32_t flags, + char * charset, + struct mail_search_key * key) +{ + clistiter * cur; + size_t length; + size_t cur_token; + int r; + + switch (key->type) { + + /* flags */ + case MAIL_SEARCH_KEY_ANSWERED: + return ((flags & MAIL_FLAG_ANSWERED) != 0); + + case MAIL_SEARCH_KEY_FLAGGED: + return ((flags & MAIL_FLAG_FLAGGED) != 0); + + case MAIL_SEARCH_KEY_DELETED: + return ((flags & MAIL_FLAG_DELETED) != 0); + + case MAIL_SEARCH_KEY_RECENT: + return ((flags & MAIL_FLAG_NEW) != 0) && + ((flags & MAIL_FLAG_SEEN) == 0); + + case MAIL_SEARCH_KEY_SEEN: + return ((flags & MAIL_FLAG_SEEN) != 0); + + case MAIL_SEARCH_KEY_NEW: + return ((flags & MAIL_FLAG_NEW) != 0); + + case MAIL_SEARCH_KEY_OLD: + return ((flags & MAIL_FLAG_NEW) == 0); + + case MAIL_SEARCH_KEY_UNANSWERED: + return ((flags & MAIL_FLAG_ANSWERED) == 0); + + case MAIL_SEARCH_KEY_UNDELETED: + return ((flags & MAIL_FLAG_DELETED) == 0); + + case MAIL_SEARCH_KEY_UNFLAGGED: + return ((flags & MAIL_FLAG_FLAGGED) == 0); + + case MAIL_SEARCH_KEY_UNSEEN: + return ((flags & MAIL_FLAG_SEEN) == 0); + + /* headers */ + case MAIL_SEARCH_KEY_BCC: + return match_header(fields, "Bcc", key->bcc); + + case MAIL_SEARCH_KEY_CC: + return match_header(fields, "Cc", key->cc); + + case MAIL_SEARCH_KEY_FROM: + return match_header(fields, "From", key->from); + + case MAIL_SEARCH_KEY_SUBJECT: + return match_header(fields, "Subject", key->subject); + + case MAIL_SEARCH_KEY_TO: + return match_header(fields, "To", key->to); + + case MAIL_SEARCH_KEY_HEADER: + return match_header(fields, key->header_name, key->header_value); + + /* date */ + case MAIL_SEARCH_KEY_BEFORE: + return (comp_date(fields, key->before) <= 0); + + case MAIL_SEARCH_KEY_ON: + return (comp_date(fields, key->before) == 0); + + case MAIL_SEARCH_KEY_SINCE: + return (comp_date(fields, key->before) >= 0); + + /* boolean */ + case MAIL_SEARCH_KEY_NOT: + return (!match_messages(message, size, fields, flags, charset, key->not)); + case MAIL_SEARCH_KEY_OR: + return (match_messages(message, size, fields, flags, charset, key->or1) || + match_messages(message, size, fields, flags, charset, key->or2)); + + case MAIL_SEARCH_KEY_MULTIPLE: + for(cur = clist_begin(key->multiple) ; cur != NULL ; + cur = clist_next(cur)) { + if (!match_messages(message, size, fields, flags, charset, + clist_content(cur))) + return FALSE; + } + + return TRUE; + + /* size */ + case MAIL_SEARCH_KEY_SMALLER: + return (size <= key->smaller); + + case MAIL_SEARCH_KEY_LARGER: + return (size >= key->larger); + + case MAIL_SEARCH_KEY_BODY: + length = strlen(message); + + cur_token = 0; + while (1) { + r = mailimf_ignore_field_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + return (strstr(message + cur_token, key->body) != NULL); + + case MAIL_SEARCH_KEY_TEXT: + return (strstr(message, key->body) != NULL); + + case MAIL_SEARCH_KEY_ALL: + default: + return TRUE; + } +} + +int maildriver_generic_search_messages(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result) +{ + int header; + clist * list; + struct mail_search_result * search_result; + int r; + struct mailmessage_list * env_list; + int res; + unsigned int i; + + header = is_search_header_only(key); + + r = mailsession_get_messages_list(session, &env_list); + if (r != MAIL_NO_ERROR) + return r; + + list = NULL; + for(i = 0 ; i < carray_count(env_list->tab) ; i ++) { + char * message; + size_t length; + struct mail_info * info; + uint32_t flags; + struct mailimf_fields * fields; + size_t cur_token; + + info = carray_get(env_list->tab, i); + + if (!header) { + r = mailsession_fetch_message(session, info->index, &message, &length); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + cur_token = 0; + r = mailimf_optional_fields_parse(message, length, + &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_PARSE; + goto free_list; + } + } + else { + char * msg_header; + int r; + size_t cur_token; + size_t header_len; + + r = mailsession_fetch_message_header(session, info->index, &msg_header, + &header_len); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + message = NULL; + cur_token = 0; + r = mailimf_optional_fields_parse(msg_header, header_len, + &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_PARSE; + goto free_list; + } + + mailsession_fetch_result_free(session, msg_header); + } + + r = mailsession_get_message_flags(session, info->index, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + if (match_messages(message, info->size, fields, flags, + charset, key)) { + uint32_t * pnum; + + pnum = malloc(sizeof(* pnum)); + if (pnum == NULL) { + if (message != NULL) + mailsession_fetch_result_free(session, message); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * pnum = info->index; + + r = clist_append(list, pnum); + if (r < 0) { + free(pnum); + if (message != NULL) + mailsession_fetch_result_free(session, message); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + if (message != NULL) + mailsession_fetch_result_free(session, message); + } + + search_result = mail_search_result_new(list); + if (search_result == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = search_result; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + mailmessage_list_free(env_list); + return res; +} +#endif + +#if 0 +int maildriver_generic_search_messages(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result) +{ + return MAIL_ERROR_NOT_IMPLEMENTED; +} +#endif + +int +maildriver_env_list_to_msg_list(struct mailmessage_list * env_list, + clist ** result) +{ + clist * msg_list; + int r; + int res; + unsigned int i; + + msg_list = clist_new(); + if (msg_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + uint32_t * pindex; + + pindex = malloc(sizeof(* pindex)); + if (pindex == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_msg_list; + } + + * pindex = msg->msg_index; + + r = clist_append(msg_list, pindex); + if (r < 0) { + free(pindex); + res = MAIL_ERROR_MEMORY; + goto free_msg_list; + } + + } + } + + * result = msg_list; + + return MAIL_NO_ERROR; + + free_msg_list: + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + err: + return res; +} + + +int +maildriver_env_list_to_msg_list_no_flags(struct mailmessage_list * env_list, + clist ** result) +{ + clist * msg_list; + int r; + int res; + unsigned int i; + + msg_list = clist_new(); + if (msg_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_flags == NULL) { + uint32_t * pindex; + + pindex = malloc(sizeof(* pindex)); + if (pindex == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_msg_list; + } + + * pindex = msg->msg_index; + + r = clist_append(msg_list, pindex); + if (r < 0) { + free(pindex); + res = MAIL_ERROR_MEMORY; + goto free_msg_list; + } + + } + } + + * result = msg_list; + + return MAIL_NO_ERROR; + + free_msg_list: + clist_foreach(msg_list, (clist_func) free, NULL); + clist_free(msg_list); + err: + return res; +} + + + +int maildriver_imf_error_to_mail_error(int error) +{ + switch (error) { + case MAILIMF_NO_ERROR: + return MAIL_NO_ERROR; + + case MAILIMF_ERROR_PARSE: + return MAIL_ERROR_PARSE; + + case MAILIMF_ERROR_MEMORY: + return MAIL_ERROR_MEMORY; + + case MAILIMF_ERROR_INVAL: + return MAIL_ERROR_INVAL; + + case MAILIMF_ERROR_FILE: + return MAIL_ERROR_FILE; + + default: + return MAIL_ERROR_INVAL; + } +} + +char * maildriver_quote_mailbox(const char * mb) +{ + MMAPString * gstr; + char * str; + + gstr = mmap_string_new(""); + if (gstr == NULL) + return NULL; + + while (* mb != 0) { + char hex[3]; + + if (((* mb >= 'a') && (* mb <= 'z')) || + ((* mb >= 'A') && (* mb <= 'Z')) || + ((* mb >= '0') && (* mb <= '9'))) + mmap_string_append_c(gstr, * mb); + else { + if (mmap_string_append_c(gstr, '%') == NULL) + goto free; + snprintf(hex, 3, "%02x", (unsigned char) (* mb)); + if (mmap_string_append(gstr, hex) == NULL) + goto free; + } + mb ++; + } + + str = strdup(gstr->str); + if (str == NULL) + goto free; + + mmap_string_free(gstr); + + return str; + + free: + mmap_string_free(gstr); + return NULL; +} + + +int maildriver_cache_clean_up(struct mail_cache_db * cache_db_env, + struct mail_cache_db * cache_db_flags, + struct mailmessage_list * env_list) +{ + chash * hash_exist; + int res; + int r; + char keyname[PATH_MAX]; + unsigned int i; + + /* flush cache */ + + hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (hash_exist == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + chashdatum key; + chashdatum value; + + msg = carray_get(env_list->msg_tab, i); + + value.data = NULL; + value.len = 0; + + if (cache_db_env != NULL) { + snprintf(keyname, PATH_MAX, "%s-envelope", msg->msg_uid); + + key.data = keyname; + key.len = strlen(keyname); + r = chash_set(hash_exist, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + } + + if (cache_db_flags != NULL) { + snprintf(keyname, PATH_MAX, "%s-flags", msg->msg_uid); + + key.data = keyname; + key.len = strlen(keyname); + r = chash_set(hash_exist, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + } + } + + /* clean up */ + if (cache_db_env != NULL) + mail_cache_db_clean_up(cache_db_env, hash_exist); + if (cache_db_flags != NULL) + mail_cache_db_clean_up(cache_db_flags, hash_exist); + + chash_free(hash_exist); + + return MAIL_NO_ERROR; + + free: + chash_free(hash_exist); + err: + return res; +} + +/* + maildriver_message_cache_clean_up() + + remove files in cache_dir that does not correspond to a message. + + get_uid_from_filename() modifies the given filename so that it + is a uid when returning from the function. If get_uid_from_filename() + clears the content of file (set to empty string), this means that + this file should not be deleted. +*/ + +int maildriver_message_cache_clean_up(char * cache_dir, + struct mailmessage_list * env_list, + void (* get_uid_from_filename)(char *)) +{ + chash * hash_exist; + DIR * d; + char cached_filename[PATH_MAX]; + struct dirent * ent; + char keyname[PATH_MAX]; + unsigned int i; + int res; + int r; + + /* remove files */ + + hash_exist = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (hash_exist == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + chashdatum key; + chashdatum value; + + msg = carray_get(env_list->msg_tab, i); + + key.data = msg->msg_uid; + key.len = strlen(msg->msg_uid); + value.data = NULL; + value.len = 0; + r = chash_set(hash_exist, &key, &value, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + } + + d = opendir(cache_dir); + while ((ent = readdir(d)) != NULL) { + chashdatum key; + chashdatum value; + + if (strcmp(ent->d_name, ".") == 0) + continue; + + if (strcmp(ent->d_name, "..") == 0) + continue; + + if (strstr(ent->d_name, ".db") != NULL) + continue; + + strncpy(keyname, ent->d_name, sizeof(keyname)); + keyname[sizeof(keyname) - 1] = '\0'; + + get_uid_from_filename(keyname); + + if (* keyname == '\0') + continue; + + key.data = keyname; + key.len = strlen(keyname); + + r = chash_get(hash_exist, &key, &value); + if (r < 0) { + snprintf(cached_filename, sizeof(cached_filename), + "%s/%s", cache_dir, ent->d_name); + unlink(cached_filename); + } + } + closedir(d); + + chash_free(hash_exist); + + return MAIL_NO_ERROR; + + free: + chash_free(hash_exist); + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_tools.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_tools.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,81 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_tools.h,v 1.15 2006/06/07 15:10:01 smarinier Exp $ + */ + +#ifndef MAILDRIVER_TOOLS_H + +#define MAILDRIVER_TOOLS_H + +#include "maildriver_types.h" +#include "mail_cache_db_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int +maildriver_generic_get_envelopes_list(mailsession * session, + struct mailmessage_list * env_list); + +#if 0 +int maildriver_generic_search_messages(mailsession * session, char * charset, + struct mail_search_key * key, + struct mail_search_result ** result); +#endif + +int +maildriver_env_list_to_msg_list(struct mailmessage_list * env_list, + clist ** result); + +int maildriver_imf_error_to_mail_error(int error); + +char * maildriver_quote_mailbox(const char * mb); + +int +maildriver_env_list_to_msg_list_no_flags(struct mailmessage_list * env_list, + clist ** result); + +int maildriver_cache_clean_up(struct mail_cache_db * cache_db_env, + struct mail_cache_db * cache_db_flags, + struct mailmessage_list * env_list); + +int maildriver_message_cache_clean_up(char * cache_dir, + struct mailmessage_list * env_list, + void (* get_uid_from_filename)(char *)); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_types.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_types.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,361 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_types.c,v 1.28 2006/06/16 09:23:38 smarinier Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "maildriver_types.h" +#include <time.h> +#include <stdlib.h> +#include "mailmessage.h" + +LIBETPAN_EXPORT +struct mailmessage_list * mailmessage_list_new(carray * msg_tab) +{ + struct mailmessage_list * env_list; + + env_list = malloc(sizeof(* env_list)); + if (env_list == NULL) + return NULL; + + env_list->msg_tab = msg_tab; + + return env_list; +} + +LIBETPAN_EXPORT +void mailmessage_list_free(struct mailmessage_list * env_list) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + if (msg != NULL) + mailmessage_free(msg); + } + carray_free(env_list->msg_tab); + free(env_list); +} + +LIBETPAN_EXPORT +struct mail_list * mail_list_new(clist * list) +{ + struct mail_list * resp; + + resp = malloc(sizeof(* resp)); + if (resp == NULL) + return NULL; + resp->mb_list = list; + + return resp; +} + +LIBETPAN_EXPORT +void mail_list_free(struct mail_list * resp) +{ + clist_foreach(resp->mb_list, (clist_func) free, NULL); + clist_free(resp->mb_list); + free(resp); +} + +static int32_t mailimf_date_time_to_int(struct mailimf_date_time * date) +{ + return date->dt_year * 12 * 30 * 24 * 60 * 60 + + date->dt_month * 30 * 24 * 60 * 60 + date->dt_day * 24 * 60 * 60 + + (date->dt_hour - date->dt_zone) * 60 * 60 + + date->dt_min * 60 + date->dt_sec; +} + +LIBETPAN_EXPORT +int32_t mailimf_date_time_comp(struct mailimf_date_time * date1, + struct mailimf_date_time * date2) +{ + return mailimf_date_time_to_int(date1) - mailimf_date_time_to_int(date2); +} + + + + + + + +#if 0 +struct mail_search_key * +mail_search_key_new(int sk_type, + char * sk_bcc, + struct mailimf_date_time * sk_before, + char * sk_body, + char * sk_cc, + char * sk_from, + struct mailimf_date_time * sk_on, + struct mailimf_date_time * sk_since, + char * sk_subject, + char * sk_text, + char * sk_to, + char * sk_header_name, + char * sk_header_value, + size_t sk_larger, + struct mail_search_key * sk_not, + struct mail_search_key * sk_or1, + struct mail_search_key * sk_or2, + size_t sk_smaller, + clist * sk_multiple) +{ + struct mail_search_key * key; + + key = malloc(sizeof(* key)); + if (key == NULL) + return NULL; + + key->sk_type = sk_type; + key->sk_bcc = sk_bcc; + key->sk_before = sk_before; + key->sk_body = sk_body; + key->sk_cc = sk_cc; + key->sk_from = sk_from; + key->sk_on = sk_on; + key->sk_since = sk_since; + key->sk_subject = sk_subject; + key->sk_text = sk_text; + key->sk_to = sk_to; + key->sk_header_name = sk_header_name; + key->sk_header_value = sk_header_value; + key->sk_larger = sk_larger; + key->sk_not = sk_not; + key->sk_or1 = sk_or1; + key->sk_or2 = sk_or2; + key->sk_smaller = sk_smaller; + key->sk_multiple = sk_multiple; + + return key; +} + + +void mail_search_key_free(struct mail_search_key * key) +{ + if (key->sk_bcc) + free(key->sk_bcc); + if (key->sk_before) + mailimf_date_time_free(key->sk_before); + if (key->sk_body) + free(key->sk_body); + if (key->sk_cc) + free(key->sk_cc); + if (key->sk_from) + free(key->sk_from); + if (key->sk_on) + mailimf_date_time_free(key->sk_on); + if (key->sk_since) + mailimf_date_time_free(key->sk_since); + if (key->sk_subject) + free(key->sk_subject); + if (key->sk_text) + free(key->sk_text); + if (key->sk_to) + free(key->sk_to); + if (key->sk_header_name) + free(key->sk_header_name); + if (key->sk_header_value) + free(key->sk_header_value); + if (key->sk_not) + mail_search_key_free(key->sk_not); + if (key->sk_or1) + mail_search_key_free(key->sk_or1); + if (key->sk_or2) + mail_search_key_free(key->sk_or2); + if (key->sk_multiple) { + clist_foreach(key->sk_multiple, (clist_func) mail_search_key_free, NULL); + clist_free(key->sk_multiple); + } + + free(key); +} + + +struct mail_search_result * mail_search_result_new(clist * list) +{ + struct mail_search_result * search_result; + + search_result = malloc(sizeof(* search_result)); + if (search_result == NULL) + return NULL; + search_result->list = list; + + return search_result; +} + +void mail_search_result_free(struct mail_search_result * search_result) +{ + clist_foreach(search_result->list, (clist_func) free, NULL); + clist_free(search_result->list); + free(search_result); +} +#endif + +struct error_message { + int code; + char * message; +}; + +static struct error_message message_tab[] = { +{ MAIL_NO_ERROR, "no error" }, +{ MAIL_NO_ERROR_AUTHENTICATED, "no error - authenticated" }, +{ MAIL_NO_ERROR_NON_AUTHENTICATED, "no error - not authenticated" }, +{ MAIL_ERROR_NOT_IMPLEMENTED, "not implemented" }, +{ MAIL_ERROR_UNKNOWN, "unknown"}, +{ MAIL_ERROR_CONNECT, "connect"}, +{ MAIL_ERROR_BAD_STATE, "bad state"}, +{ MAIL_ERROR_FILE, "file error - file could not be accessed" }, +{ MAIL_ERROR_STREAM, "stream error - socket could not be read or written" }, +{ MAIL_ERROR_LOGIN, "login error" }, +{ MAIL_ERROR_CREATE, "create error" }, +{ MAIL_ERROR_DELETE, /* 10 */ "delete error" }, +{ MAIL_ERROR_LOGOUT, "logout error" }, +{ MAIL_ERROR_NOOP, "noop error" }, +{ MAIL_ERROR_RENAME, "rename error" }, +{ MAIL_ERROR_CHECK, "check error" }, +{ MAIL_ERROR_EXAMINE, "examine error" }, +{ MAIL_ERROR_SELECT, "select error - folder does not exist" }, +{ MAIL_ERROR_MEMORY, "not enough memory" }, +{ MAIL_ERROR_STATUS, "status error" }, +{ MAIL_ERROR_SUBSCRIBE, "subscribe error" }, +{ MAIL_ERROR_UNSUBSCRIBE, /* 20 */ "unsubscribe error" }, +{ MAIL_ERROR_LIST, "list error" }, +{ MAIL_ERROR_LSUB, "lsub error" }, +{ MAIL_ERROR_APPEND, "append error - mail could not be appended" }, +{ MAIL_ERROR_COPY, "copy error" }, +{ MAIL_ERROR_FETCH, "fetch error" }, +{ MAIL_ERROR_STORE, "store error" }, +{ MAIL_ERROR_SEARCH, "search error" }, +{ MAIL_ERROR_DISKSPACE, " error: not enough diskspace" }, +{ MAIL_ERROR_MSG_NOT_FOUND, "message not found" }, +{ MAIL_ERROR_PARSE, /* 30 */ "parse error" }, +{ MAIL_ERROR_INVAL, "invalid parameter for the function" }, +{ MAIL_ERROR_PART_NOT_FOUND, "mime part of the message is not found" }, +{ MAIL_ERROR_REMOVE, "remove error - the message did not exist" }, +{ MAIL_ERROR_FOLDER_NOT_FOUND, "folder not found" }, +{ MAIL_ERROR_MOVE, "move error" }, +{ MAIL_ERROR_STARTTLS, "starttls error" }, +{ MAIL_ERROR_CACHE_MISS, "mail cache missed" }, +{ MAIL_ERROR_NO_TLS, "no starttls" }, +{ MAIL_ERROR_EXPUNGE, "expunge error" }, +{ MAIL_ERROR_PROTOCOL, "protocol error - server did not respect the protocol" }, +{ MAIL_ERROR_CAPABILITY, "capability error" }, +{ MAIL_ERROR_CLOSE, "close error" }, +{ MAIL_ERROR_FATAL, "fatal error" }, +{ MAIL_ERROR_READONLY, "mailbox is readonly" }, +{ MAIL_ERROR_NO_APOP, "pop3 error - no apop" }, +{ MAIL_ERROR_COMMAND_NOT_SUPPORTED, "nntp error - command not supported" }, +{ MAIL_ERROR_NO_PERMISSION, "nntp error - no permission" }, +{ MAIL_ERROR_PROGRAM_ERROR, "nntp error - program error" }, +{ MAIL_ERROR_SUBJECT_NOT_FOUND, "internal threading error - subject not found" }}; + +LIBETPAN_EXPORT +const char * maildriver_strerror(int err) +{ + int count; + int i; + + count = sizeof(message_tab) / sizeof(struct error_message); + + for(i = 0 ; i < count ; i++) { + if (message_tab[i].code == err) { + return message_tab[i].message; + } + } + + return "unknown error"; +} + +LIBETPAN_EXPORT +struct mail_flags * mail_flags_new_empty(void) +{ + struct mail_flags * flags; + + flags = malloc(sizeof(* flags)); + if (flags == NULL) + goto err; + + flags->fl_flags = MAIL_FLAG_NEW; + flags->fl_extension = clist_new(); + if (flags->fl_extension == NULL) + goto free; + + return flags; + + free: + free(flags); + err: + return NULL; +} + +LIBETPAN_EXPORT +struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_extension) +{ + struct mail_flags * flags; + + flags = malloc(sizeof(* flags)); + if (flags == NULL) + goto err; + + flags->fl_flags = fl_flags; + flags->fl_extension = fl_extension; + + return flags; + +err: + return NULL; +} + +LIBETPAN_EXPORT +void mail_flags_free(struct mail_flags * flags) +{ + clist_foreach(flags->fl_extension, (clist_func) free, NULL); + clist_free(flags->fl_extension); + free(flags); +} + +LIBETPAN_EXPORT +void *libetpan_malloc(size_t length) { + return malloc( length); +} + +LIBETPAN_EXPORT +void libetpan_free(void* data) { + free( data); +} Added: freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,827 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_types.h,v 1.47 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifndef MAILDRIVER_TYPES_H + +#define MAILDRIVER_TYPES_H + +#ifndef _MSC_VER +# ifdef HAVE_INTTYPES_H +# include <inttypes.h> +# endif +# include <sys/types.h> +#endif + +#include <libetpan/mailstream.h> +#include <libetpan/mailimf.h> +#include <libetpan/mailmime.h> +#include <libetpan/carray.h> + +#include <libetpan/mailthread_types.h> +#include <libetpan/maildriver_errors.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mailsession_driver mailsession_driver; + +typedef struct mailsession mailsession; + +typedef struct mailmessage_driver mailmessage_driver; + +typedef struct mailmessage mailmessage; + + +/* + mailmessage_list is a list of mailmessage + + - tab is an array of mailmessage structures +*/ + +struct mailmessage_list { + carray * msg_tab; /* elements are (mailmessage *) */ +}; + +LIBETPAN_EXPORT +struct mailmessage_list * mailmessage_list_new(carray * msg_tab); + +LIBETPAN_EXPORT +void mailmessage_list_free(struct mailmessage_list * env_list); + +/* + mail_list is a list of mailbox names + + - list is a list of mailbox names +*/ + +struct mail_list { + clist * mb_list; /* elements are (char *) */ +}; + +LIBETPAN_EXPORT +struct mail_list * mail_list_new(clist * mb_list); + +LIBETPAN_EXPORT +void mail_list_free(struct mail_list * resp); + +/* + This is a flag value. + Flags can be combined with OR operation +*/ + +enum { + MAIL_FLAG_NEW = 1 << 0, + MAIL_FLAG_SEEN = 1 << 1, + MAIL_FLAG_FLAGGED = 1 << 2, + MAIL_FLAG_DELETED = 1 << 3, + MAIL_FLAG_ANSWERED = 1 << 4, + MAIL_FLAG_FORWARDED = 1 << 5, + MAIL_FLAG_CANCELLED = 1 << 6 +}; + +/* + mail_flags is the value of a flag related to a message. + + - flags is the standard flags value + + - extension is a list of unknown flags for libEtPan! +*/ + +struct mail_flags { + uint32_t fl_flags; + clist * fl_extension; /* elements are (char *) */ +}; + +LIBETPAN_EXPORT +struct mail_flags * mail_flags_new(uint32_t fl_flags, clist * fl_ext); + +LIBETPAN_EXPORT +void mail_flags_free(struct mail_flags * flags); + +/* + This function creates a flag for a new message +*/ + +LIBETPAN_EXPORT +struct mail_flags * mail_flags_new_empty(void); + + +/* + mailimf_date_time_comp compares two dates + + +*/ + +LIBETPAN_EXPORT +int32_t mailimf_date_time_comp(struct mailimf_date_time * date1, + struct mailimf_date_time * date2); + +/* + this is type type of the search criteria +*/ + +enum { + MAIL_SEARCH_KEY_ALL, /* all messages correspond */ + MAIL_SEARCH_KEY_ANSWERED, /* messages with flag \Answered */ + MAIL_SEARCH_KEY_BCC, /* messages which Bcc field contains + a given string */ + MAIL_SEARCH_KEY_BEFORE, /* messages which internal date is earlier + than the specified date */ + MAIL_SEARCH_KEY_BODY, /* message that contains the given string + (in header and text parts) */ + MAIL_SEARCH_KEY_CC, /* messages whose Cc field contains the + given string */ + MAIL_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */ + MAIL_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */ + MAIL_SEARCH_KEY_FROM, /* messages whose From field contains the + given string */ + MAIL_SEARCH_KEY_NEW, /* messages with the flag \Recent and not + the \Seen flag */ + MAIL_SEARCH_KEY_OLD, /* messages that do not have the + \Recent flag set */ + MAIL_SEARCH_KEY_ON, /* messages whose internal date is the + specified date */ + MAIL_SEARCH_KEY_RECENT, /* messages with the flag \Recent */ + MAIL_SEARCH_KEY_SEEN, /* messages with the flag \Seen */ + MAIL_SEARCH_KEY_SINCE, /* messages whose internal date is later + than specified date */ + MAIL_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the + given string */ + MAIL_SEARCH_KEY_TEXT, /* messages whose text part contains the + given string */ + MAIL_SEARCH_KEY_TO, /* messages whose To field contains the + given string */ + MAIL_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */ + MAIL_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */ + MAIL_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */ + MAIL_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */ + MAIL_SEARCH_KEY_HEADER, /* messages whose given field + contains the given string */ + MAIL_SEARCH_KEY_LARGER, /* messages whose size is larger then + the given size */ + MAIL_SEARCH_KEY_NOT, /* not operation of the condition */ + MAIL_SEARCH_KEY_OR, /* or operation between two conditions */ + MAIL_SEARCH_KEY_SMALLER, /* messages whose size is smaller than + the given size */ + MAIL_SEARCH_KEY_MULTIPLE /* the boolean operator between the + conditions is AND */ +}; + +/* + mail_search_key is the condition on the messages to return + + - type is the type of the condition + + - bcc is the text to search in the Bcc field when type is + MAIL_SEARCH_KEY_BCC, should be allocated with malloc() + + - before is a date when type is MAIL_SEARCH_KEY_BEFORE + + - body is the text to search in the message when type is + MAIL_SEARCH_KEY_BODY, should be allocated with malloc() + + - cc is the text to search in the Cc field when type is + MAIL_SEARCH_KEY_CC, should be allocated with malloc() + + - from is the text to search in the From field when type is + MAIL_SEARCH_KEY_FROM, should be allocated with malloc() + + - on is a date when type is MAIL_SEARCH_KEY_ON + + - since is a date when type is MAIL_SEARCH_KEY_SINCE + + - subject is the text to search in the Subject field when type is + MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc() + + - text is the text to search in the text part of the message when + type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc() + + - to is the text to search in the To field when type is + MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc() + + - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER, + should be allocated with malloc() + + - header_value is the text to search in the given header when type is + MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc() + + - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER + + - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT + + - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE + + - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON + + - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE + + - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER + + - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE +*/ + +#if 0 +struct mail_search_key { + int sk_type; + union { + char * sk_bcc; + struct mailimf_date_time * sk_before; + char * sk_body; + char * sk_cc; + char * sk_from; + struct mailimf_date_time * sk_on; + struct mailimf_date_time * sk_since; + char * sk_subject; + char * sk_text; + char * sk_to; + char * sk_header_name; + char * sk_header_value; + size_t sk_larger; + struct mail_search_key * sk_not; + struct mail_search_key * sk_or1; + struct mail_search_key * sk_or2; + size_t sk_smaller; + clist * sk_multiple; /* list of (struct mailimap_search_key *) */ + } sk_data; +}; + + +struct mail_search_key * +mail_search_key_new(int sk_type, + char * sk_bcc, struct mailimf_date_time * sk_before, + char * sk_body, char * sk_cc, char * sk_from, + struct mailimf_date_time * sk_on, struct mailimf_date_time * sk_since, + char * sk_subject, char * sk_text, char * sk_to, + char * sk_header_name, char * sk_header_value, size_t sk_larger, + struct mail_search_key * sk_not, struct mail_search_key * sk_or1, + struct mail_search_key * sk_or2, size_t sk_smaller, + clist * sk_multiple); + +void mail_search_key_free(struct mail_search_key * key); +#endif + +/* + mail_search_result is a list of message numbers that is returned + by the mailsession_search_messages function() +*/ + +#if 0 +struct mail_search_result { + clist * sr_list; /* list of (uint32_t *) */ +}; + +struct mail_search_result * mail_search_result_new(clist * sr_list); + +void mail_search_result_free(struct mail_search_result * search_result); +#endif + + +/* + There is three kinds of identities : + - storage + - folders + - session + + A storage (struct mailstorage) represents whether a server or + a main path, + + A storage can be an IMAP server, the root path of a MH or a mbox file. + + Folders (struct mailfolder) are the mailboxes we can + choose in the server or as sub-folder of the main path. + + Folders for IMAP are the IMAP mailboxes, for MH this is one of the + folder of the MH storage, for mbox, there is only one folder, the + mbox file content; + + A mail session (struct mailsession) is whether a connection to a server + or a path that is open. It is the abstraction lower folders and storage. + It allow us to send commands. + + We have a session driver for mail session for each kind of storage. + + From a session, we can get a message (struct mailmessage) to read. + We have a message driver for each kind of storage. +*/ + +/* + maildriver is the driver structure for mail sessions + + - name is the name of the driver + + - initialize() is the function that will initializes a data structure + specific to the driver, it returns a value that will be stored + in the field data of the session. + The field data of the session is the state of the session, + the internal data structure used by the driver. + It is called when creating the mailsession structure with + mailsession_new(). + + - uninitialize() frees the structure created with initialize() + + - parameters() implements functions specific to the given mail access + + - connect_stream() connects a stream to the session + + - connect_path() notify a main path to the session + + - starttls() changes the current stream to a TLS stream + + - login() notifies the user and the password to authenticate to the + session + + - logout() exits the session and closes the stream + + - noop() does no operation on the session, but it can be + used to poll for the status of the connection. + + - build_folder_name() will return an allocated string with + that contains the complete path of the folder to create + + - create_folder() creates the folder that corresponds to the + given name + + - delete_folder() deletes the folder that corresponds to the + given name + + - rename_folder() change the name of the folder + + - check_folder() makes a checkpoint of the session + + - examine_folder() selects a mailbox as readonly + + - select_folder() selects a mailbox + + - expunge_folder() deletes all messages marked \Deleted + + - status_folder() queries the status of the folder + (number of messages, number of recent messages, number of + unseen messages) + + - messages_number() queries the number of messages in the folder + + - recent_number() queries the number of recent messages in the folder + + - unseen_number() queries the number of unseen messages in the folder + + - list_folders() returns the list of all sub-mailboxes + of the given mailbox + + - lsub_folders() returns the list of subscribed + sub-mailboxes of the given mailbox + + - subscribe_folder() subscribes to the given mailbox + + - unsubscribe_folder() unsubscribes to the given mailbox + + - append_message() adds a RFC 2822 message to the current + given mailbox + + - copy_message() copies a message whose number is given to + a given mailbox. The mailbox must be accessible from + the same session. + + - move_message() copies a message whose number is given to + a given mailbox. The mailbox must be accessible from the + same session. + + - get_messages_list() returns the list of message numbers + of the current mailbox. + + - get_envelopes_list() fills the parsed fields in the + mailmessage structures of the mailmessage_list. + + - remove_message() removes the given message from the mailbox. + The message is permanently deleted. + + - search_message() returns a list of message numbers that + corresponds to the given criteria. + + - get_message returns a mailmessage structure that corresponds + to the given message number. + + - get_message_by_uid returns a mailmessage structure that corresponds + to the given message unique identifier. + + * mandatory functions are the following : + + - connect_stream() of connect_path() + - logout() + - get_messages_list() + - get_envelopes_list() + + * we advise you to implement these functions : + + - select_folder() (in case a session can access several folders) + - noop() (to check if the server is responding) + - check_folder() (to make a checkpoint of the session) + - status_folder(), messages_number(), recent_number(), unseen_number() + (to get stat of the folder) + - append_message() (but can't be done in the case of POP3 at least) + - login() in a case of an authenticated driver. + - starttls() in a case of a stream driver, if the procotol supports + STARTTLS. + - get_message_by_uid() so that the application can remember the message + by UID and build its own list of messages. + - login_sasl() notifies the SASL information to authenticate to the + session. + + * drivers' specific : + + Everything that is specific to the driver will be implemented in this + function : + + - parameters() +*/ + +struct mailsession_driver { + char * sess_name; + + int (* sess_initialize)(mailsession * session); + void (* sess_uninitialize)(mailsession * session); + + int (* sess_parameters)(mailsession * session, + int id, void * value); + + int (* sess_connect_stream)(mailsession * session, mailstream * s); + int (* sess_connect_path)(mailsession * session, const char * path); + + int (* sess_starttls)(mailsession * session); + + int (* sess_login)(mailsession * session, const char * userid, const char * password); + int (* sess_logout)(mailsession * session); + int (* sess_noop)(mailsession * session); + + /* folders operations */ + + int (* sess_build_folder_name)(mailsession * session, const char * mb, + const char * name, char ** result); + + int (* sess_create_folder)(mailsession * session, const char * mb); + int (* sess_delete_folder)(mailsession * session, const char * mb); + int (* sess_rename_folder)(mailsession * session, const char * mb, + const char * new_name); + int (* sess_check_folder)(mailsession * session); + int (* sess_examine_folder)(mailsession * session, const char * mb); + int (* sess_select_folder)(mailsession * session, const char * mb); + int (* sess_expunge_folder)(mailsession * session); + int (* sess_status_folder)(mailsession * session, const char * mb, + uint32_t * result_num, uint32_t * result_recent, + uint32_t * result_unseen); + int (* sess_messages_number)(mailsession * session, const char * mb, + uint32_t * result); + int (* sess_recent_number)(mailsession * session, const char * mb, + uint32_t * result); + int (* sess_unseen_number)(mailsession * session, const char * mb, + uint32_t * result); + + int (* sess_list_folders)(mailsession * session, const char * mb, + struct mail_list ** result); + int (* sess_lsub_folders)(mailsession * session, const char * mb, + struct mail_list ** result); + + int (* sess_subscribe_folder)(mailsession * session, const char * mb); + int (* sess_unsubscribe_folder)(mailsession * session, const char * mb); + + /* messages operations */ + + int (* sess_append_message)(mailsession * session, + const char * message, size_t size); + int (* sess_append_message_flags)(mailsession * session, + const char * message, size_t size, struct mail_flags * flags); + int (* sess_copy_message)(mailsession * session, + uint32_t num, const char * mb); + int (* sess_move_message)(mailsession * session, + uint32_t num, const char * mb); + + int (* sess_get_message)(mailsession * session, + uint32_t num, mailmessage ** result); + + int (* sess_get_message_by_uid)(mailsession * session, + const char * uid, mailmessage ** result); + + int (* sess_get_messages_list)(mailsession * session, + struct mailmessage_list ** result); + int (* sess_get_envelopes_list)(mailsession * session, + struct mailmessage_list * env_list); + int (* sess_remove_message)(mailsession * session, uint32_t num); +#if 0 + int (* sess_search_messages)(mailsession * session, const char * charset, + struct mail_search_key * key, + struct mail_search_result ** result); +#endif + + int (* sess_login_sasl)(mailsession * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); +}; + + +/* + session is the data structure for a mail session. + + - data is the internal data structure used by the driver + It is called when initializing the mailsession structure. + + - driver is the driver used for the session +*/ + +struct mailsession { + void * sess_data; + mailsession_driver * sess_driver; +}; + + + + +/* + mailmessage_driver is the driver structure to get information from messages. + + - name is the name of the driver + + - initialize() is the function that will initializes a data structure + specific to the driver, it returns a value that will be stored + in the field data of the mailsession. + The field data of the session is the state of the session, + the internal data structure used by the driver. + It is called when initializing the mailmessage structure with + mailmessage_init(). + + - uninitialize() frees the structure created with initialize(). + It will be called by mailmessage_free(). + + - flush() will free from memory all temporary structures of the message + (for example, the MIME structure of the message). + + - fetch_result_free() will free all strings resulted by fetch() or + any fetch_xxx() functions that returns a string. + + - fetch() returns the content of the message (headers and text). + + - fetch_header() returns the content of the headers. + + - fetch_body() returns the message text (message content without headers) + + - fetch_size() returns the size of the message content. + + - get_bodystructure() returns the MIME structure of the message. + + - fetch_section() returns the content of a given MIME part + + - fetch_section_header() returns the header of the message + contained by the given MIME part. + + - fetch_section_mime() returns the MIME headers of the + given MIME part. + + - fetch_section_body() returns the text (if this is a message, this is the + message content without headers) of the given MIME part. + + - fetch_envelope() returns a mailimf_fields structure, with a list of + fields chosen by the driver. + + - get_flags() returns a the flags related to the message. + When you want to get flags of a message, you have to make sure to + call get_flags() at least once before using directly message->flags. +*/ + +#define LIBETPAN_MAIL_MESSAGE_CHECK + +struct mailmessage_driver { + char * msg_name; + + int (* msg_initialize)(mailmessage * msg_info); + + void (* msg_uninitialize)(mailmessage * msg_info); + + void (* msg_flush)(mailmessage * msg_info); + + void (* msg_check)(mailmessage * msg_info); + + void (* msg_fetch_result_free)(mailmessage * msg_info, + char * msg); + + int (* msg_fetch)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_header)(mailmessage * msg_info, + char ** result, + size_t * result_len); + + int (* msg_fetch_body)(mailmessage * msg_info, + char ** result, size_t * result_len); + + int (* msg_fetch_size)(mailmessage * msg_info, + size_t * result); + + int (* msg_get_bodystructure)(mailmessage * msg_info, + struct mailmime ** result); + + int (* msg_fetch_section)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + + int (* msg_fetch_section_header)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_mime)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_section_body)(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + + int (* msg_fetch_envelope)(mailmessage * msg_info, + struct mailimf_fields ** result); + + int (* msg_get_flags)(mailmessage * msg_info, + struct mail_flags ** result); +}; + + +/* + mailmessage is a data structure to get information from messages + + - session is the session linked to the given message, it can be NULL + + - driver is the message driver + + - index is the message number + + - uid, when it is not NULL, it means that the folder + the folder has persistant message numbers, the string is + the unique message number in the folder. + uid should be implemented if possible. + for drivers where we cannot generate real uid, + a suggestion is "AAAA-IIII" where AAAA is some + random session number and IIII the content of index field. + + - size, when it is not 0, is the size of the message content. + + - fields, when it is not NULL, are the header fields of the message. + + - flags, when it is not NULL, are the flags related to the message. + + - single_fields, when resolved != 0, is filled with the data of fields. + + - mime, when it is not NULL + + - cached is != 0 when the header fields were read from the cache. + + - data is data specific to the driver, this is internal data structure, + some state of the message. +*/ + +struct mailmessage { + mailsession * msg_session; + mailmessage_driver * msg_driver; + uint32_t msg_index; + char * msg_uid; + + size_t msg_size; + struct mailimf_fields * msg_fields; + struct mail_flags * msg_flags; + + int msg_resolved; + struct mailimf_single_fields msg_single_fields; + struct mailmime * msg_mime; + + /* internal data */ + + int msg_cached; + void * msg_data; + + /* + msg_folder field : + used to reference the mailfolder, this is a workaround due + to the problem with initial conception, where folder notion + did not exist. + */ + void * msg_folder; + /* user data */ + void * msg_user_data; +}; + + +/* + mailmessage_tree is a node in the messages tree (thread) + + - parent is the parent of the message, it is NULL if the message + is the root of the message tree. + + - date is the date of the message in number of second elapsed + since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC). + + - msg is the message structure that is stored referenced by the node. + is msg is NULL, this is a dummy node. + + - children is an array that contains all the children of the node. + children are mailmessage_tree structures. + + - is_reply is != 0 when the message is a reply or a forward + + - base_subject is the extracted subject of the message. + + - index is the message number. +*/ + +struct mailmessage_tree { + struct mailmessage_tree * node_parent; + char * node_msgid; + time_t node_date; + mailmessage * node_msg; + carray * node_children; /* array of (struct mailmessage_tree *) */ + + /* private, used for threading */ + int node_is_reply; + char * node_base_subject; +}; + +LIBETPAN_EXPORT +struct mailmessage_tree * +mailmessage_tree_new(char * node_msgid, time_t node_date, + mailmessage * node_msg); + +LIBETPAN_EXPORT +void mailmessage_tree_free(struct mailmessage_tree * tree); + +/* + mailmessage_tree_free_recursive + + if you want to release memory of the given tree and all the sub-trees, + you can use this function. +*/ +LIBETPAN_EXPORT +void mailmessage_tree_free_recursive(struct mailmessage_tree * tree); + + +struct generic_message_t { + int (* msg_prefetch)(mailmessage * msg_info); + void (* msg_prefetch_free)(struct generic_message_t * msg); + int msg_fetched; + char * msg_message; + size_t msg_length; + void * msg_data; +}; + +LIBETPAN_EXPORT +const char * maildriver_strerror(int err); + +/* basic malloc / free functions to be compliant with the library allocations */ +LIBETPAN_EXPORT +void *libetpan_malloc(size_t length); + +LIBETPAN_EXPORT +void libetpan_free(void* data); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_types_helper.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_types_helper.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,108 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 200 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_types_helper.c,v 1.5 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "maildriver_types_helper.h" + +#include "mail.h" + +#include "clist.h" +#include <string.h> +#include <stdlib.h> + +int mail_flags_add_extension(struct mail_flags * flags, + char * ext_flag) +{ + char * str; + int r; + + if (mail_flags_has_extension(flags, ext_flag)) + return MAIL_NO_ERROR; + + str = strdup(ext_flag); + if (str == NULL) + return MAIL_ERROR_MEMORY; + + r = clist_append(flags->fl_extension, str); + if (r < 0) { + free(str); + return MAIL_ERROR_MEMORY; + } + + return MAIL_NO_ERROR; +} + +int mail_flags_remove_extension(struct mail_flags * flags, + char * ext_flag) +{ + clistiter * cur; + + cur = clist_begin(flags->fl_extension); + while (cur != NULL) { + char * flag_name; + + flag_name = clist_content(cur); + + if (strcasecmp(flag_name, ext_flag) == 0) { + free(flag_name); + cur = clist_delete(flags->fl_extension, cur); + } + else + cur = clist_next(cur); + } + + return MAIL_NO_ERROR; +} + +int mail_flags_has_extension(struct mail_flags * flags, + char * ext_flag) +{ + clistiter * cur; + + for(cur = clist_begin(flags->fl_extension) ; cur != NULL ; + cur = clist_next(cur)) { + char * flag_name; + + flag_name = clist_content(cur); + + if (strcasecmp(flag_name, ext_flag) == 0) + return TRUE; + } + + return FALSE; +} Added: freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_types_helper.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/maildriver_types_helper.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,99 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildriver_types_helper.h,v 1.6 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef MAILDRIVER_TYPES_HELPER_H + +#define MAILDRIVER_TYPES_HELPER_H + +#include <libetpan/maildriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mail_flags_add_extension adds the given flag if it does not exists in + the flags. + + @param flags this is the flag to change + + @param ext_flag this is the name of an extension flag + the given flag name is duplicated and is no more needed after + the function call. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_flags_add_extension(struct mail_flags * flags, + char * ext_flag); + +/* + mail_flags_remove_extension removes the given flag if it does not exists in + the flags. + + @param flags this is the flag to change + + @param ext_flag this is the name of an extension flag + the given flag name is no more needed after the function call. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_flags_remove_extension(struct mail_flags * flags, + char * ext_flag); + +/* + mail_flags_has_extension returns 1 if the flags is in the given flags, + 0 is returned otherwise. + + @param flags this is the flag to change + + @param ext_flag this is the name of an extension flag + the given flag name is no more needed after the function call. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_flags_has_extension(struct mail_flags * flags, + char * ext_flag); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/interface/mailfolder.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/mailfolder.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,169 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailfolder.c,v 1.6 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailfolder.h" + +#include <string.h> + +#include "maildriver.h" +#include "mailstorage.h" + +LIBETPAN_EXPORT +int mailfolder_noop(struct mailfolder * folder) +{ + return mailsession_noop(folder->fld_session); +} + +LIBETPAN_EXPORT +int mailfolder_check(struct mailfolder * folder) +{ + return mailsession_check_folder(folder->fld_session); +} + +LIBETPAN_EXPORT +int mailfolder_expunge(struct mailfolder * folder) +{ + return mailsession_expunge_folder(folder->fld_session); +} + +LIBETPAN_EXPORT +int mailfolder_status(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen) +{ + return mailsession_status_folder(folder->fld_session, + folder->fld_pathname, result_messages, + result_recent, result_unseen); +} + +LIBETPAN_EXPORT +int mailfolder_append_message(struct mailfolder * folder, + char * message, size_t size) +{ + return mailsession_append_message(folder->fld_session, message, size); +} + +LIBETPAN_EXPORT +int mailfolder_append_message_flags(struct mailfolder * folder, + char * message, size_t size, struct mail_flags * flags) +{ + return mailsession_append_message_flags(folder->fld_session, message, + size, flags); +} + +LIBETPAN_EXPORT +int mailfolder_get_messages_list(struct mailfolder * folder, + struct mailmessage_list ** result) +{ + int r; + struct mailmessage_list * msg_list; + unsigned int i; + struct mailstorage * storage; + + /* workaround for POP3 case - begin */ + storage = folder->fld_storage; + if (strcmp(storage->sto_driver->sto_name, "pop3") == 0) { + mailstorage_disconnect(storage); + r = mailstorage_connect(storage); + if (r != MAIL_NO_ERROR) + return r; + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) + return r; + } + /* workaround for POP3 case - begin */ + + r = mailsession_get_messages_list(folder->fld_session, &msg_list); + if (r != MAIL_NO_ERROR) + return r; + + for(i = 0 ; i < carray_count(msg_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(msg_list->msg_tab, i); + msg->msg_folder = folder; + } + + * result = msg_list; + + return MAIL_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailfolder_get_envelopes_list(struct mailfolder * folder, + struct mailmessage_list * result) +{ + return mailsession_get_envelopes_list(folder->fld_session, result); +} + +LIBETPAN_EXPORT +int mailfolder_get_message(struct mailfolder * folder, + uint32_t num, mailmessage ** result) +{ + mailmessage * msg; + int r; + + r = mailsession_get_message(folder->fld_session, num, &msg); + if (r != MAIL_NO_ERROR) + return r; + + msg->msg_folder = folder; + + * result = msg; + + return MAIL_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailfolder_get_message_by_uid(struct mailfolder * folder, + const char * uid, mailmessage ** result) +{ + mailmessage * msg; + int r; + + r = mailsession_get_message_by_uid(folder->fld_session, uid, &msg); + if (r != MAIL_NO_ERROR) + return r; + + msg->msg_folder = folder; + + * result = msg; + + return MAIL_NO_ERROR; +} Added: freeswitch/trunk/libs/libetpan/src/driver/interface/mailfolder.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/mailfolder.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,80 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailfolder.h,v 1.4 2006/04/06 22:54:56 hoa Exp $ + */ + +#ifndef MAILFOLDER_H + +#define MAILFOLDER_H + +#include "mailstorage_types.h" + +LIBETPAN_EXPORT +int mailfolder_noop(struct mailfolder * folder); + +LIBETPAN_EXPORT +int mailfolder_check(struct mailfolder * folder); + +LIBETPAN_EXPORT +int mailfolder_expunge(struct mailfolder * folder); + +LIBETPAN_EXPORT +int mailfolder_status(struct mailfolder * folder, + uint32_t * result_messages, uint32_t * result_recent, + uint32_t * result_unseen); + +LIBETPAN_EXPORT +int mailfolder_append_message(struct mailfolder * folder, + char * message, size_t size); + +LIBETPAN_EXPORT +int mailfolder_append_message_flags(struct mailfolder * folder, + char * message, size_t size, struct mail_flags * flags); + +LIBETPAN_EXPORT +int mailfolder_get_messages_list(struct mailfolder * folder, + struct mailmessage_list ** result); + +LIBETPAN_EXPORT +int mailfolder_get_envelopes_list(struct mailfolder * folder, + struct mailmessage_list * result); + +LIBETPAN_EXPORT +int mailfolder_get_message(struct mailfolder * folder, + uint32_t num, mailmessage ** result); + +LIBETPAN_EXPORT +int mailfolder_get_message_by_uid(struct mailfolder * folder, + const char * uid, mailmessage ** result); + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,259 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmessage.c,v 1.17 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmessage.h" + +#include "mail.h" + +#include <string.h> + +LIBETPAN_EXPORT +int mailmessage_init(mailmessage * msg_info, + mailsession * msg_session, + mailmessage_driver * msg_driver, + uint32_t msg_index, size_t msg_size) +{ + int r; + int res; + + msg_info->msg_driver = msg_driver; + msg_info->msg_session = msg_session; + msg_info->msg_index = msg_index; + msg_info->msg_uid = NULL; + + msg_info->msg_cached = FALSE; + msg_info->msg_size = msg_size; + msg_info->msg_fields = NULL; + memset(&msg_info->msg_single_fields, 0, + sizeof(struct mailimf_single_fields)); + msg_info->msg_resolved = FALSE; + msg_info->msg_flags = NULL; + + msg_info->msg_mime = NULL; + msg_info->msg_data = NULL; + msg_info->msg_folder = NULL; + msg_info->msg_user_data = NULL; + + if (msg_driver->msg_initialize != NULL) { + r = msg_driver->msg_initialize(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + return MAIL_NO_ERROR; + + err: + msg_info->msg_driver = NULL; + msg_info->msg_session = NULL; + return res; +} + +LIBETPAN_EXPORT +int mailmessage_flush(mailmessage * msg_info) +{ + if (msg_info->msg_driver->msg_flush == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + msg_info->msg_driver->msg_flush(msg_info); + + return MAIL_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailmessage_check(mailmessage * msg_info) +{ + if (msg_info->msg_driver->msg_check == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + msg_info->msg_driver->msg_check(msg_info); + + return MAIL_NO_ERROR; +} +LIBETPAN_EXPORT +int mailmessage_fetch_result_free(mailmessage * msg_info, + char * msg) +{ + if (msg_info->msg_driver->msg_fetch_result_free == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + msg_info->msg_driver->msg_fetch_result_free(msg_info, msg); + + return MAIL_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailmessage_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch(msg_info, result, result_len); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_header == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_header(msg_info, result, result_len); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_body == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_body(msg_info, result, result_len); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_size(mailmessage * msg_info, + size_t * result) +{ + if (msg_info->msg_driver->msg_fetch_size == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_size(msg_info, result); +} + +LIBETPAN_EXPORT +int mailmessage_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result) +{ + if (msg_info->msg_driver->msg_get_bodystructure == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_get_bodystructure(msg_info, result); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_section == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_section(msg_info, mime, result, result_len); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_section_header == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_section_header(msg_info, mime, + result, result_len); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_section_mime == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_section_mime(msg_info, mime, + result, result_len); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + if (msg_info->msg_driver->msg_fetch_section_body == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_section_body(msg_info, mime, + result, result_len); +} + +LIBETPAN_EXPORT +int mailmessage_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result) +{ + if (msg_info->msg_driver->msg_fetch_envelope == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return msg_info->msg_driver->msg_fetch_envelope(msg_info, result); +} + +LIBETPAN_EXPORT +int mailmessage_get_flags(mailmessage * msg_info, + struct mail_flags ** result) +{ + struct mail_flags * dummy; + + if (msg_info->msg_driver->msg_get_flags == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + if (result != NULL) + return msg_info->msg_driver->msg_get_flags(msg_info, result); + else + return msg_info->msg_driver->msg_get_flags(msg_info, &dummy); +} + +LIBETPAN_EXPORT +void mailmessage_resolve_single_fields(mailmessage * msg_info) +{ + if (!msg_info->msg_resolved) { + if (msg_info->msg_fields != NULL) { + mailimf_single_fields_init(&msg_info->msg_single_fields, + msg_info->msg_fields); + msg_info->msg_resolved = TRUE; + } + } +} Added: freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,379 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmessage.h,v 1.16 2005/06/01 12:22:00 smarinier Exp $ + */ + +#include <libetpan/mailmessage_types.h> + +#ifndef MAILMESSAGE_H + +#define MAILMESSAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mailmessage_new + + This function will initializes a new empty message. + + @return a new empty message will be returned. +*/ +LIBETPAN_EXPORT +mailmessage * mailmessage_new(void); + +/* + mailmessage_free + + This function will release the memory used by this message. +*/ +LIBETPAN_EXPORT +void mailmessage_free(mailmessage * info); + +/* + mailmessage_init + + This function will initializes a mailmessage structure + with a message from a given session. + + @param msg_info This is the message to initialize. + + @param session This is the source session of the message. It + can be NULL if the message does not get the information + through the session. + + @param driver This is the driver to use for the message. + + @param index This is the message number in the session. 0 can + be given if the message is not attached to a session. + + @param size is an optional parameter, 0 can be given. + This is informational. This is the size of message content. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ +LIBETPAN_EXPORT +int mailmessage_init(mailmessage * msg_info, + mailsession * session, + mailmessage_driver * driver, + uint32_t index, size_t size); + +/* + mailmessage_flush + + This function will release all the temporary resources that are not + necessary to use the mailmessage structure from memory. These + resources are for example cached information, such as the MIME + structure. + + @param info is the message to clean. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. We can assume that MAIL_NO_ERROR is always returned. +*/ +LIBETPAN_EXPORT +int mailmessage_flush(mailmessage * info); + +/* + mailmessage_check + + This function will notify the new value of the flags to the session, + it must be called before mailsession_check_folder() in case the flags have + been changed. + + @param info is the message to checkpoint. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. We can assume that MAIL_NO_ERROR is always returned. +*/ +LIBETPAN_EXPORT +int mailmessage_check(mailmessage * info); + +/* + mailmessage_fetch_result_free + + This function releases the memory used by a message returned + by any of the fetch function that returns a (char *). + + @param msg_info is the message which the given buffer is from. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. We can assume that MAIL_NO_ERROR is always returned. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_result_free(mailmessage * msg_info, + char * msg); + +/* + mailmessage_fetch + + This function returns the content of the message (headers and text). + + @param msg_info is the message from which we want to fetch information. + + @param result The content of the message is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_header + + This function returns the header of the message as a string. + + @param msg_info is the message from which we want to fetch information. + + @param result The header of the message is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_body + + This function returns the content of the message (without headers). + + @param msg_info is the message from which we want to fetch information. + @param result The message text (without headers) is returned + in (* result) + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + +/* + mailmessage_fetch_size + + This function returns the size of the message content. + + @param msg_info is the message from which we want to fetch information. + + @param result The length of the message content is stored in (* result). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_size(mailmessage * msg_info, + size_t * result); + +/* + mailmessage_get_bodystructure + + This functions returns the MIME structure of the message. + The returned information MUST not be freed by hand. It is freed by + mailmessage_flush() or mailmessage_free(). + + @param msg_info is the message from which we want to fetch information. + + @param result The MIME structure is stored in (* result). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result); + +/* + mailmessage_fetch_section + + This function returns the content of a MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The content is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. + */ +LIBETPAN_EXPORT +int mailmessage_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +/* + mailmessage_fetch_section_header + + This function returns the header of the message contained + in the given MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The header is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_section_mime + + This function returns the MIME header of the given MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The MIME header is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_section_body + + This function returns the text part of the message contained + in the given MIME part. + + @param msg_info is the message from which we want to fetch information. + + @param mime is the MIME part identifier. + + @param result The message text is returned in (* result) + + @param result_len The length of the returned string is stored + in (* result_len). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. + */ +LIBETPAN_EXPORT +int mailmessage_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +/* + mailmessage_fetch_envelope + + This function returns a list of parsed fields of the message, + chosen by the driver. + The returned structure must be freed with mailimf_fields_free(). + + @param msg_info is the message from which we want to fetch information. + + @param result The headers list is returned in (* result) + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. + */ +LIBETPAN_EXPORT +int mailmessage_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + + +/* + mailmessage_get_flags + + This function returns the flags related to the message. + The returned information MUST not be freed by hand. It is freed by + mailmessage_free(). + + @param msg_info is the message from which we want to fetch information. + + @param result The flags are stored in (* result). + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +int mailmessage_get_flags(mailmessage * msg_info, + struct mail_flags ** result); + +/* + mailmessage_resolve_single_fields + + This function will use the fields information to fill the single_fields + structure in the mailmessage structure. + + @param msg_info This is the msg_info to process. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error. +*/ +LIBETPAN_EXPORT +void mailmessage_resolve_single_fields(mailmessage * msg_info); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage_tools.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage_tools.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,604 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmessage_tools.c,v 1.24 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmessage_tools.h" +#include "mailmessage.h" + +#include <stdlib.h> + +#include "maildriver.h" +#include "maildriver_tools.h" + +int +mailmessage_generic_initialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + + msg = malloc(sizeof(* msg)); + + if (msg == NULL) { + return MAIL_ERROR_MEMORY; + } + + msg->msg_fetched = 0; + msg->msg_message = NULL; + msg->msg_length = 0; + + msg->msg_prefetch = NULL; + msg->msg_prefetch_free = NULL; + msg->msg_data = NULL; + + msg_info->msg_data = msg; + + return MAIL_NO_ERROR; +} + +void mailmessage_generic_flush(mailmessage * msg_info) +{ + struct generic_message_t * msg; + + if (msg_info->msg_mime != NULL) { + mailmime_free(msg_info->msg_mime); + msg_info->msg_mime = NULL; + } + msg = msg_info->msg_data; + if (msg != NULL) { + if (msg->msg_prefetch_free != NULL) + msg->msg_prefetch_free(msg); + msg->msg_fetched = 0; + } +} + +void mailmessage_generic_uninitialize(mailmessage * msg_info) +{ + struct generic_message_t * msg; + + mailmessage_generic_flush(msg_info); + + msg = msg_info->msg_data; + msg_info->msg_data = NULL; + free(msg); +} + +static inline int +mailmessage_generic_prefetch(mailmessage * msg_info) +{ + struct generic_message_t * msg; + int r; + + msg = msg_info->msg_data; + + if (msg->msg_fetched) + return MAIL_NO_ERROR; + +#if 0 + if (msg->message != NULL) + return MAIL_NO_ERROR; +#endif + + r = msg->msg_prefetch(msg_info); + if (r != MAIL_NO_ERROR) + return r; + + msg->msg_fetched = 1; + + return MAIL_NO_ERROR; +} + +static int +mailmessage_generic_prefetch_bodystructure(mailmessage * msg_info) +{ + size_t length; + char * message; + size_t cur_token; + struct mailmime * mime; + int r; + int res; + struct generic_message_t * msg; + + if (msg_info->msg_mime != NULL) { + /* it has already been fetched */ + return MAIL_NO_ERROR; + } + +#if 0 + msg = msg_info->data; + if (msg->message == NULL) { + r = mailmessage_generic_prefetch(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } +#endif + r = mailmessage_generic_prefetch(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + msg = msg_info->msg_data; + message = msg->msg_message; + length = msg->msg_length; + cur_token = 0; + r = mailmime_parse(message, length, &cur_token, &mime); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_PARSE; + goto err; + } + + msg_info->msg_mime = mime; + + return MAIL_NO_ERROR; + + err: + return res; +} + +void +mailmessage_generic_fetch_result_free(mailmessage * msg_info, char * msg) +{ + int r; + + r = mmap_string_unref(msg); +} + +int mailmessage_generic_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + int r; + char * message; + size_t cur_token; + size_t length; + MMAPString * mmapstr; + int res; + struct generic_message_t * msg; + + msg = msg_info->msg_data; + r = mailmessage_generic_prefetch(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + message = msg->msg_message; + length = msg->msg_length; + cur_token = 0; + + mmapstr = mmap_string_new_len(message, length); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = length; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int mailmessage_generic_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + int r; + char * message; + size_t cur_token; + size_t length; + MMAPString * mmapstr; + char * headers; + int res; + struct generic_message_t * msg; + + msg = msg_info->msg_data; + r = mailmessage_generic_prefetch(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + message = msg->msg_message; + length = msg->msg_length; + cur_token = 0; + + while (1) { + r = mailimf_ignore_field_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + mailimf_crlf_parse(message, length, &cur_token); + + mmapstr = mmap_string_new_len(message, cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + headers = mmapstr->str; + + * result = headers; + * result_len = cur_token; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int mailmessage_generic_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len) +{ + int r; + char * message; + size_t cur_token; + MMAPString * mmapstr; + size_t length; + int res; + struct generic_message_t * msg; + + msg = msg_info->msg_data; + r = mailmessage_generic_prefetch(msg_info); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + message = msg->msg_message; + length = msg->msg_length; + cur_token = 0; + + while (1) { + r = mailimf_ignore_field_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + mailimf_crlf_parse(message, length, &cur_token); + + mmapstr = mmap_string_new_len(message + cur_token, length - cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = length - cur_token; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + + + + +int +mailmessage_generic_get_bodystructure(mailmessage * msg_info, + struct mailmime ** result) +{ + int r; + + r = mailmessage_generic_prefetch_bodystructure(msg_info); + if (r != MAIL_NO_ERROR) + return r; + + * result = msg_info->msg_mime; + + return MAIL_NO_ERROR; +} + + + + +int +mailmessage_generic_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + MMAPString * mmapstr; + int r; + int res; + + mmapstr = mmap_string_new_len(mime->mm_body->dt_data.dt_text.dt_data, + mime->mm_body->dt_data.dt_text.dt_length); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int +mailmessage_generic_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + int r; + int res; + size_t cur_token; + + /* skip mime */ + + cur_token = 0; + + if (mime->mm_type == MAILMIME_MESSAGE) { + + while (1) { + r = mailimf_ignore_field_parse(mime->mm_body->dt_data.dt_text.dt_data, + mime->mm_body->dt_data.dt_text.dt_length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(mime->mm_body->dt_data.dt_text.dt_data, + mime->mm_body->dt_data.dt_text.dt_length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto err; + } + } + + mmapstr = mmap_string_new_len(mime->mm_body->dt_data.dt_text.dt_data, + cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int +mailmessage_generic_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + int r; + int res; + size_t cur_token; + + cur_token = 0; + + /* skip header */ + + while (1) { + r = mailimf_ignore_field_parse(mime->mm_mime_start, + mime->mm_length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(mime->mm_mime_start, mime->mm_length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto err; + } + + mmapstr = mmap_string_new_len(mime->mm_mime_start, cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int +mailmessage_generic_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + int r; + int res; + size_t cur_token; + + cur_token = 0; + + if (mime->mm_type == MAILMIME_MESSAGE) { + + /* skip header */ + + while (1) { + r = mailimf_ignore_field_parse(mime->mm_body->dt_data.dt_text.dt_data, + mime->mm_body->dt_data.dt_text.dt_length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else + break; + } + + r = mailimf_crlf_parse(mime->mm_body->dt_data.dt_text.dt_data, + mime->mm_body->dt_data.dt_text.dt_length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = maildriver_imf_error_to_mail_error(r); + goto err; + } + } + + mmapstr = mmap_string_new_len(mime->mm_body->dt_data.dt_text.dt_data + + cur_token, mime->mm_body->dt_data.dt_text.dt_length - cur_token); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_mmap; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return MAIL_NO_ERROR; + + free_mmap: + mmap_string_free(mmapstr); + err: + return res; +} + +int mailmessage_generic_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result) +{ + int r; + int res; + size_t cur_token; + char * header; + size_t length; + struct mailimf_fields * fields; + + r = mailmessage_fetch_header(msg_info, &header, &length); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + cur_token = 0; + + r = mailimf_envelope_fields_parse(header, length, &cur_token, + &fields); + if (r != MAILIMF_NO_ERROR) { + res = maildriver_imf_error_to_mail_error(r); + goto free; + /* do nothing */ + } + + mailmessage_fetch_result_free(msg_info, header); + + * result = fields; + + return MAIL_NO_ERROR; + + free: + mailmessage_fetch_result_free(msg_info, header); + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage_tools.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage_tools.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,103 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmessage_tools.h,v 1.7 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef MAILMESSAGE_TOOLS_H + +#define MAILMESSAGE_TOOLS_H + +#include "mailmessage_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int +mailmessage_generic_initialize(mailmessage * + msg_info); + +void mailmessage_generic_uninitialize(mailmessage * + msg_info); + +void mailmessage_generic_flush(mailmessage * msg_info); + +void mailmessage_generic_fetch_result_free(mailmessage * msg_info, + char * msg); + +int mailmessage_generic_fetch(mailmessage * msg_info, + char ** result, + size_t * result_len); + +int mailmessage_generic_fetch_header(mailmessage * msg_info, + char ** result, + size_t * result_len); + +int mailmessage_generic_fetch_body(mailmessage * msg_info, + char ** result, size_t * result_len); + +int mailmessage_generic_get_bodystructure(mailmessage * + msg_info, + struct mailmime ** result); + +int +mailmessage_generic_fetch_section(mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +int +mailmessage_generic_fetch_section_header(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +int +mailmessage_generic_fetch_section_mime(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +int +mailmessage_generic_fetch_section_body(mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +int mailmessage_generic_fetch_envelope(mailmessage * msg_info, + struct mailimf_fields ** result); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage_types.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage_types.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,98 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmessage_types.c,v 1.13 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmessage_types.h" + +#include "mail.h" + +#include <stdlib.h> +#include <string.h> + +LIBETPAN_EXPORT +mailmessage * mailmessage_new(void) +{ + mailmessage * msg_info; + + msg_info = malloc(sizeof(* msg_info)); + if (msg_info == NULL) + goto err; + + msg_info->msg_driver = NULL; + msg_info->msg_session = NULL; + msg_info->msg_index = 0; + msg_info->msg_uid = NULL; + + msg_info->msg_cached = FALSE; + msg_info->msg_size = 0; + msg_info->msg_fields = NULL; + memset(&msg_info->msg_single_fields, + 0, sizeof(struct mailimf_single_fields)); + msg_info->msg_resolved = FALSE; + msg_info->msg_flags = NULL; + + msg_info->msg_mime = NULL; + msg_info->msg_data = NULL; + + msg_info->msg_folder = NULL; + msg_info->msg_user_data = NULL; + + return msg_info; + + err: + return NULL; +} + +LIBETPAN_EXPORT +void mailmessage_free(mailmessage * msg_info) +{ + if (msg_info->msg_driver != NULL) { + if (msg_info->msg_driver->msg_uninitialize != NULL) + msg_info->msg_driver->msg_uninitialize(msg_info); + } + + if (msg_info->msg_fields != NULL) + mailimf_fields_free(msg_info->msg_fields); + if (msg_info->msg_mime != NULL) + mailmime_free(msg_info->msg_mime); + if (msg_info->msg_flags != NULL) + mail_flags_free(msg_info->msg_flags); + if (msg_info->msg_uid != NULL) + free(msg_info->msg_uid); + free(msg_info); +} Added: freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/mailmessage_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,50 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmessage_types.h,v 1.9 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef MAILMESSAGE_TYPES_H + +#define MAILMESSAGE_TYPES_H + +#include <libetpan/maildriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/interface/mailstorage.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/mailstorage.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,356 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstorage.c,v 1.24 2006/06/02 15:44:30 smarinier Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailstorage.h" + +#include "maildriver.h" + +#include <stdlib.h> +#include <string.h> + +static int mailstorage_get_folder(struct mailstorage * storage, + char * pathname, mailsession ** result); + +LIBETPAN_EXPORT +struct mailfolder * mailfolder_new(struct mailstorage * storage, + const char * pathname, const char * virtual_name) +{ + struct mailfolder * folder; + + folder = malloc(sizeof(struct mailfolder)); + if (folder == NULL) + goto err; + + if (pathname != NULL) { + folder->fld_pathname = strdup(pathname); + if (folder->fld_pathname == NULL) + goto free; + } + else + folder->fld_pathname = NULL; + + if (virtual_name != NULL) { + folder->fld_virtual_name = strdup(virtual_name); + if (folder->fld_virtual_name == NULL) + goto free_pathname; + } + else + folder->fld_virtual_name = NULL; + + folder->fld_storage = storage; + + folder->fld_session = NULL; + folder->fld_shared_session = 0; + folder->fld_pos = NULL; + + folder->fld_parent = NULL; + folder->fld_sibling_index = 0; + folder->fld_children = carray_new(128); + if (folder->fld_children == NULL) + goto free_virtualname; + + return folder; + +free_virtualname: + if (folder->fld_virtual_name != NULL) + free(folder->fld_virtual_name); +free_pathname: + if (folder->fld_pathname != NULL) + free(folder->fld_pathname); +free: + free(folder); +err: + return NULL; +} + +LIBETPAN_EXPORT +void mailfolder_free(struct mailfolder * folder) +{ + if (folder->fld_parent != NULL) + mailfolder_detach_parent(folder); + + while (carray_count(folder->fld_children) > 0) { + struct mailfolder * child; + + child = carray_get(folder->fld_children, 0); + mailfolder_detach_parent(child); + } + + carray_free(folder->fld_children); + + if (folder->fld_session != NULL) + mailfolder_disconnect(folder); + + if (folder->fld_virtual_name != NULL) + free(folder->fld_virtual_name); + if (folder->fld_pathname != NULL) + free(folder->fld_pathname); + free(folder); +} + +LIBETPAN_EXPORT +int mailfolder_connect(struct mailfolder * folder) +{ + mailsession * session; + int res; + int r; + + if (folder->fld_storage == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + if (folder->fld_storage->sto_session == NULL) { + r = mailstorage_connect(folder->fld_storage); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + if (folder->fld_session != NULL) { + if ((folder->fld_pathname != NULL) && (folder->fld_shared_session)) { + if (folder->fld_session->sess_driver->sess_select_folder != NULL) { + r = mailsession_select_folder(folder->fld_session, + folder->fld_pathname); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + } + + return MAIL_NO_ERROR; + } + + r = mailstorage_get_folder(folder->fld_storage, folder->fld_pathname, + &session); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + folder->fld_session = session; + folder->fld_shared_session = (session == folder->fld_storage->sto_session); + if (folder->fld_shared_session) { + r = clist_append(folder->fld_storage->sto_shared_folders, folder); + if (r < 0) { + folder->fld_session = NULL; + res = MAIL_ERROR_MEMORY; + goto err; + } + folder->fld_pos = clist_end(folder->fld_storage->sto_shared_folders); + } + + return MAIL_NO_ERROR; + +err: + return res; +} + +LIBETPAN_EXPORT +void mailfolder_disconnect(struct mailfolder * folder) +{ + if (folder->fld_session == NULL) + return; + + if (folder->fld_shared_session) { + clist_delete(folder->fld_storage->sto_shared_folders, folder->fld_pos); + folder->fld_pos = NULL; + } + else { + mailsession_logout(folder->fld_session); + mailsession_free(folder->fld_session); + } + + folder->fld_session = NULL; +} + +LIBETPAN_EXPORT +int mailfolder_add_child(struct mailfolder * parent, + struct mailfolder * child) +{ + unsigned int index; + int r; + + r = carray_add(parent->fld_children, child, &index); + if (r < 0) + return MAIL_ERROR_MEMORY; + + child->fld_sibling_index = index; + child->fld_parent = parent; + + return MAIL_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailfolder_detach_parent(struct mailfolder * folder) +{ + unsigned int i; + int r; + + if (folder->fld_parent == NULL) + return MAIL_ERROR_INVAL; + + r = carray_delete_slow(folder->fld_parent->fld_children, + folder->fld_sibling_index); + if (r < 0) + return MAIL_ERROR_INVAL; + + for(i = 0 ; i < carray_count(folder->fld_parent->fld_children) ; i ++) { + struct mailfolder * child; + + child = carray_get(folder->fld_parent->fld_children, i); + child->fld_sibling_index = i; + } + + folder->fld_parent = NULL; + folder->fld_sibling_index = 0; + + return MAIL_NO_ERROR; +} + +LIBETPAN_EXPORT +struct mailstorage * mailstorage_new(const char * sto_id) +{ + struct mailstorage * storage; + + storage = malloc(sizeof(struct mailstorage)); + if (storage == NULL) + goto err; + + if (sto_id != NULL) { + storage->sto_id = strdup(sto_id); + if (storage->sto_id == NULL) + goto free; + } + else + storage->sto_id = NULL; + + storage->sto_data = NULL; + storage->sto_session = NULL; + storage->sto_driver = NULL; + storage->sto_shared_folders = clist_new(); + if (storage->sto_shared_folders == NULL) + goto free_id; + + return storage; + + free_id: + if (storage->sto_id != NULL) + free(storage->sto_id); + free: + free(storage); + err: + return NULL; +} + +LIBETPAN_EXPORT +void mailstorage_free(struct mailstorage * storage) +{ + if (storage->sto_session != NULL) + mailstorage_disconnect(storage); + + if (storage->sto_driver != NULL) { + if (storage->sto_driver->sto_uninitialize != NULL) + storage->sto_driver->sto_uninitialize(storage); + } + + clist_free(storage->sto_shared_folders); + + if (storage->sto_id != NULL) + free(storage->sto_id); + + free(storage); +} + +LIBETPAN_EXPORT +int mailstorage_connect(struct mailstorage * storage) +{ + if (storage->sto_session != NULL) + return MAIL_NO_ERROR; + + if (!clist_isempty(storage->sto_shared_folders)) + return MAIL_ERROR_BAD_STATE; + + if (storage->sto_driver->sto_connect == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return storage->sto_driver->sto_connect(storage); +} + + +LIBETPAN_EXPORT +void mailstorage_disconnect(struct mailstorage * storage) +{ + int r; + clistiter * cur; + + while ((cur = clist_begin(storage->sto_shared_folders)) != NULL) { + struct mailfolder * folder; + + folder = cur->data; + mailfolder_disconnect(folder); + } + + if (storage->sto_session == NULL) + return; + + r = mailsession_logout(storage->sto_session); + + mailsession_free(storage->sto_session); + storage->sto_session = NULL; +} + + +LIBETPAN_EXPORT +int mailstorage_noop(struct mailstorage * storage) +{ + return mailsession_noop(storage->sto_session); +} + + +static int mailstorage_get_folder(struct mailstorage * storage, + char * pathname, mailsession ** result) +{ + if (storage->sto_driver->sto_get_folder_session == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + return storage->sto_driver->sto_get_folder_session(storage, + pathname, result); +} Added: freeswitch/trunk/libs/libetpan/src/driver/interface/mailstorage.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/mailstorage.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,110 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstorage.h,v 1.17 2006/06/02 15:44:30 smarinier Exp $ + */ + +#ifndef MAIL_STORAGE_H + +#define MAIL_STORAGE_H + +#include <libetpan/maildriver_types.h> +#include <libetpan/mailstorage_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* storage */ + +/* + mailstorage_new + + This function creates an empty storage. This storage have to be initialized. + The "driver" and "data" fields should be initialized. + + @param id is the name of the storage. It can be NULL. + The given parameter is no more needed when the creation is finished. + The given string is duplicated. + + @return The mail storage is returned. +*/ + +LIBETPAN_EXPORT +struct mailstorage * mailstorage_new(const char * sto_id); + +LIBETPAN_EXPORT +void mailstorage_free(struct mailstorage * storage); + +/* + session will be initialized on success. +*/ + +LIBETPAN_EXPORT +int mailstorage_connect(struct mailstorage * storage); + +LIBETPAN_EXPORT +void mailstorage_disconnect(struct mailstorage * storage); + +LIBETPAN_EXPORT +int mailstorage_noop(struct mailstorage * storage); + + +/* folder */ + +LIBETPAN_EXPORT +struct mailfolder * mailfolder_new(struct mailstorage * fld_storage, + const char * fld_pathname, const char * fld_virtual_name); + +LIBETPAN_EXPORT +void mailfolder_free(struct mailfolder * folder); + +LIBETPAN_EXPORT +int mailfolder_add_child(struct mailfolder * parent, + struct mailfolder * child); + +LIBETPAN_EXPORT +int mailfolder_detach_parent(struct mailfolder * folder); + +LIBETPAN_EXPORT +int mailfolder_connect(struct mailfolder * folder); + +LIBETPAN_EXPORT +void mailfolder_disconnect(struct mailfolder * folder); + +#ifdef __cplusplus +} +#endif + +#endif + + Added: freeswitch/trunk/libs/libetpan/src/driver/interface/mailstorage_tools.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/mailstorage_tools.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,429 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstorage_tools.c,v 1.20 2006/07/15 12:24:26 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailstorage_tools.h" + +#include "libetpan-config.h" + +#include <sys/types.h> +#include <stdlib.h> +#ifndef _MSC_VER +# include <netdb.h> +# include <netinet/in.h> +# include <sys/socket.h> +# include <unistd.h> +# include <sys/wait.h> +# include <sys/ioctl.h> +#endif +#include <fcntl.h> +#include <string.h> +#include <stdio.h> + +#include "mail.h" +#include "mailmessage.h" +#include "maildriver.h" + +/* tools */ + +/* connection to TCP/IP server */ + +static int tcp_connect(char * server, uint16_t port) +{ + return mail_tcp_connect(server, port); +} + +/* connection through a shell command */ +/* SEB unsupported on Windows */ +#ifndef WIN32 + +#define ENV_BUFFER_SIZE 512 + +static void do_exec_command(int fd, const char *command, + char *servername, uint16_t port) +{ + int i, maxopen; +#ifdef SOLARIS + char env_buffer[ENV_BUFFER_SIZE]; +#endif + + if (fork() > 0) { + /* Fork again to become a child of init rather than + the etpan client. */ + exit(0); + } + +#ifdef SOLARIS + if (servername) + snprintf(env_buffer, ENV_BUFFER_SIZE, "ETPANSERVER=%s", servername); + else + snprintf(env_buffer, ENV_BUFFER_SIZE, "ETPANSERVER="); + putenv(env_buffer); +#else + if (servername) + setenv("ETPANSERVER", servername, 1); + else + unsetenv("ETPANSERVER"); +#endif + +#ifdef SOLARIS + if (port) + snprintf(env_buffer, ENV_BUFFER_SIZE, "ETPANPORT=%d", port); + else + snprintf(env_buffer, ENV_BUFFER_SIZE, "ETPANPORT="); + putenv(env_buffer); +#else + if (port) { + char porttext[20]; + + snprintf(porttext, sizeof(porttext), "%d", port); + setenv("ETPANPORT", porttext, 1); + } + else { + unsetenv("ETPANPORT"); + } +#endif + + /* Not a lot we can do if there's an error other than bail. */ + if (dup2(fd, 0) == -1) + exit(1); + if (dup2(fd, 1) == -1) + exit(1); + + /* Should we close stderr and reopen /dev/null? */ + + maxopen = sysconf(_SC_OPEN_MAX); + for (i=3; i < maxopen; i++) + close(i); + +#ifdef TIOCNOTTY + /* Detach from the controlling tty if we have one. Otherwise, + SSH might do something stupid like trying to use it instead + of running $SSH_ASKPASS. Doh. */ + fd = open("/dev/tty", O_RDONLY); + if (fd != -1) { + ioctl(fd, TIOCNOTTY, NULL); + close(fd); + } +#endif /* TIOCNOTTY */ + + execl("/bin/sh", "/bin/sh", "-c", command, NULL); + + /* Eep. Shouldn't reach this */ + exit(1); +} +#endif /* WIN32 */ + +static int subcommand_connect(char *command, char *servername, uint16_t port) +{ +/* SEB unsupported on Windows */ +#ifdef WIN32 + return -1; +#else + + int sockfds[2]; + pid_t childpid; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) + return -1; + + childpid = fork(); + if (!childpid) { + do_exec_command(sockfds[1], command, servername, port); + } + else if (childpid == -1) { + close(sockfds[0]); + close(sockfds[1]); + return -1; + } + + close(sockfds[1]); + + /* Reap child, leaving grandchild process to run */ + waitpid(childpid, NULL, 0); + + return sockfds[0]; +#endif /* WIN32 */ +} + +int mailstorage_generic_connect(mailsession_driver * driver, + char * servername, + uint16_t port, + char * command, + int connection_type, + int cache_function_id, + char * cache_directory, + int flags_function_id, + char * flags_directory, + mailsession ** result) +{ + int r; + int res; + mailstream * stream; + int fd; + mailsession * session; + int connect_result; + + switch (connection_type) { + case CONNECTION_TYPE_PLAIN: + case CONNECTION_TYPE_TRY_STARTTLS: + case CONNECTION_TYPE_STARTTLS: + case CONNECTION_TYPE_TLS: + fd = tcp_connect(servername, port); + if (fd == -1) { + res = MAIL_ERROR_CONNECT; + goto err; + } + break; + + case CONNECTION_TYPE_COMMAND: + case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: + case CONNECTION_TYPE_COMMAND_STARTTLS: + case CONNECTION_TYPE_COMMAND_TLS: + fd = subcommand_connect(command, servername, port); + break; + default: + fd = -1; + break; + } + + if (fd == -1) { + res = MAIL_ERROR_INVAL; + goto err; + } + + switch (connection_type) { + case CONNECTION_TYPE_PLAIN: + case CONNECTION_TYPE_TRY_STARTTLS: + case CONNECTION_TYPE_STARTTLS: + case CONNECTION_TYPE_COMMAND: + case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: + case CONNECTION_TYPE_COMMAND_STARTTLS: + stream = mailstream_socket_open(fd); + break; + + case CONNECTION_TYPE_TLS: + case CONNECTION_TYPE_COMMAND_TLS: + stream = mailstream_ssl_open(fd); + break; + + default: + stream = NULL; + break; + } + + if (stream == NULL) { + res = MAIL_ERROR_STREAM; + close(fd); + goto err; + } + + session = mailsession_new(driver); + if (session == NULL) { + res = MAIL_ERROR_MEMORY; + goto close_stream; + } + + if (cache_directory != NULL) { + char cache_directory_server[PATH_MAX]; + + snprintf(cache_directory_server, PATH_MAX, "%s/%s", + cache_directory, servername); + + r = mailsession_parameters(session, + cache_function_id, + cache_directory_server); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_stream; + } + } + + if (flags_directory != NULL) { + char flags_directory_server[PATH_MAX]; + + snprintf(flags_directory_server, PATH_MAX, "%s/%s", + flags_directory, servername); + + r = mailsession_parameters(session, + flags_function_id, + flags_directory_server); + if (r != MAIL_NO_ERROR) { + res = r; + goto close_stream; + } + } + + r = mailsession_connect_stream(session, stream); + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto free; + } + + connect_result = r; + + switch (connection_type) { + case CONNECTION_TYPE_TRY_STARTTLS: + case CONNECTION_TYPE_COMMAND_TRY_STARTTLS: + r = mailsession_starttls(session); + if ((r != MAIL_NO_ERROR) && (r != MAIL_ERROR_NO_TLS)) { + res = r; + goto free; + } + break; + + case CONNECTION_TYPE_STARTTLS: + case CONNECTION_TYPE_COMMAND_STARTTLS: + r = mailsession_starttls(session); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } + + * result = session; + + return connect_result; + + close_stream: + mailstream_close(stream); + free: + mailsession_free(session); + err: + return res; +} + + + + + +int mailstorage_generic_auth(mailsession * session, + int connect_result, + int auth_type, + char * login, + char * password) +{ + int must_auth; + int r; + int res; + + r = connect_result; + + must_auth = FALSE; + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + must_auth = TRUE; + break; + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto err; + } + + if ((login == NULL) || (password == NULL)) + must_auth = FALSE; + + if (must_auth) { + r = mailsession_login(session, login, password); + if (r != MAIL_NO_ERROR) { + mailsession_logout(session); + res = r; + goto err; + } + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +int mailstorage_generic_auth_sasl(mailsession * session, + int connect_result, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ + int must_auth; + int r; + int res; + + r = connect_result; + + must_auth = FALSE; + switch (r) { + case MAIL_NO_ERROR_NON_AUTHENTICATED: + must_auth = TRUE; + break; + case MAIL_NO_ERROR_AUTHENTICATED: + case MAIL_NO_ERROR: + break; + default: + res = r; + goto err; + } + + if (must_auth) { + r = mailsession_login_sasl(session, auth_type, + server_fqdn, + local_ip_port, + remote_ip_port, + login, auth_name, + password, realm); + if (r != MAIL_NO_ERROR) { + mailsession_logout(session); + res = r; + goto err; + } + } + + return MAIL_NO_ERROR; + + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/driver/interface/mailstorage_tools.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/mailstorage_tools.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,76 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstorage_tools.h,v 1.7 2005/08/15 11:08:41 hoa Exp $ + */ + +#include "mailstorage.h" + +#ifndef MAILSTORAGE_TOOLS_H + +#define MAILSTORAGE_TOOLS_H + +#ifdef __cplusplus +extern "C" { +#endif + +int mailstorage_generic_connect(mailsession_driver * driver, + char * servername, + uint16_t port, + char * command, + int connection_type, + int cache_function_id, + char * cache_directory, + int flags_function_id, + char * flags_directory, + mailsession ** result); + +int mailstorage_generic_auth(mailsession * session, + int connect_result, + int auth_type, + char * login, + char * password); + +int mailstorage_generic_auth_sasl(mailsession * session, + int connect_result, + const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/interface/mailstorage_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/interface/mailstorage_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,203 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailstorage_types.h,v 1.9 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MAILSTORAGE_TYPES_H + +#define MAILSTORAGE_TYPES_H + +#include <libetpan/maildriver_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct mailstorage; + +typedef struct mailstorage_driver mailstorage_driver; + + +/* + There is three kinds of identities : + - storage + - folders + - session + + A storage (struct mailstorage) represents whether a server or + a main path, + + A storage can be an IMAP server, the root path of a MH or a mbox file. + + Folders (struct mailfolder) are the mailboxes we can + choose in the server or as sub-folder of the main path. + + Folders for IMAP are the IMAP mailboxes, for MH this is one of the + folder of the MH storage, for mbox, there is only one folder, the + mbox file content; + + A mail session (struct mailsession) is whether a connection to a server + or a path that is open. It is the abstraction lower folders and storage. + It allow us to send commands. + + We have a session driver for mail session for each kind of storage. + + From a session, we can get a message (struct mailmessage) to read. + We have a message driver for each kind of storage. +*/ + +/* + mailstorage_driver is the driver structure for mail storages + + - name is the name of the driver + + - connect() connects the storage to the remote access or to + the path in the local filesystem. + + - get_folder() can have two kinds of behaviour. + Either it creates a new session and independant from the session + used by the storage and select the given mailbox or + it selects the given mailbox in the current session. + It depends on the efficiency of the mail driver. + + - uninitialize() frees the data created with mailstorage constructor. +*/ + +struct mailstorage_driver { + char * sto_name; + int (* sto_connect)(struct mailstorage * storage); + int (* sto_get_folder_session)(struct mailstorage * storage, + char * pathname, mailsession ** result); + void (* sto_uninitialize)(struct mailstorage * storage); +}; + +/* + mailstorage is the data structure for a storage + + - id is the name of the storage, it can be NULL. + + - data is the data specific to the driver. + This is the internal state of the storage. + + - session is the session related to the storage. + + - driver is the driver for the storage. + + - shared_folders is the list of folders returned by the storage. +*/ + +struct mailstorage { + char * sto_id; + void * sto_data; + mailsession * sto_session; + mailstorage_driver * sto_driver; + clist * sto_shared_folders; /* list of (struct mailfolder *) */ + + void * sto_user_data; +}; + + + +/* + mailfolder is the data structure for a mailbox + + - pathname is the path of the mailbox on the storage + + - virtual_name is the folder identifier, it can be a path, + a name or NULL. + + - storage is the storage to which the folder belongs to. + + - session is the session related to the folder. It can be + different of the session of the storage. + + - shared_session is != 0 if the session is the same as the + session of the storage. + + - pos is the position of the folder in the "shared_folders" field + of the storage. + + folders can be chained into a tree. + + - parent is the parent of the folder. + + - sibling_index is the index of the folder in the list of children + of the parent. + + - children is the folder. +*/ + +struct mailfolder { + char * fld_pathname; + char * fld_virtual_name; + + struct mailstorage * fld_storage; + + mailsession * fld_session; + int fld_shared_session; + clistiter * fld_pos; + + struct mailfolder * fld_parent; + unsigned int fld_sibling_index; + carray * fld_children; /* array of (struct mailfolder *) */ + + void * fld_user_data; +}; + +/* + this is the type of socket connection +*/ + +enum { + CONNECTION_TYPE_PLAIN, /* when the connection is plain text */ + CONNECTION_TYPE_STARTTLS, /* when the connection is first plain, + then, we want to switch to + TLS (secure connection) */ + CONNECTION_TYPE_TRY_STARTTLS, /* the connection is first plain, + then, we will try to switch to TLS */ + CONNECTION_TYPE_TLS, /* the connection is over TLS */ + CONNECTION_TYPE_COMMAND, /* the connection is over a shell command */ + CONNECTION_TYPE_COMMAND_STARTTLS, /* the connection is over a shell + command and STARTTLS will be used */ + CONNECTION_TYPE_COMMAND_TRY_STARTTLS, /* the connection is over + a shell command and STARTTLS will + be tried */ + CONNECTION_TYPE_COMMAND_TLS /* the connection is over a shell + command in TLS */ +}; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/tools/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/tools/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/driver/tools/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/tools/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,16 @@ +HEADERS = \ + generic_cache_types.h \ + mailthread.h mailthread_types.h + + +SOURCES = \ + generic_cache.c imfcache.c \ + mailthread.c mailthread_types.c + + +TARGET = libtools +INCLUDES = -I../../low-level/imf -I../../low-level/mime -I../../data-types \ + -I../interface + +top_builddir = ../../.. +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/driver/tools/generic_cache.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/tools/generic_cache.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,754 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: generic_cache.c,v 1.32 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "generic_cache.h" + +#include "libetpan-config.h" + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif +#ifdef _MSC_VER +# include "win_etpan.h" +#endif +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> + +#include "maildriver_types.h" +#include "imfcache.h" +#include "chash.h" +#include "mailmessage.h" +#include "mail_cache_db.h" + +int generic_cache_create_dir(char * dirname) +{ + struct stat buf; + int r; + + r = stat(dirname, &buf); + if (r != 0) { + +#ifdef WIN32 + r = mkdir(dirname); +#else + r = mkdir(dirname, 0700); +#endif + + if (r < 0) + return MAIL_ERROR_FILE; + } + else { + if (!S_ISDIR(buf.st_mode)) + return MAIL_ERROR_FILE; + } + + return MAIL_NO_ERROR; +} + +int generic_cache_store(char * filename, char * content, size_t length) +{ + int fd; + char * str; + + fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + if (fd == -1) + return MAIL_ERROR_FILE; + + if (ftruncate(fd, length) < 0) + return MAIL_ERROR_FILE; + + str = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (str == (char *)MAP_FAILED) + return MAIL_ERROR_FILE; + + memcpy(str, content, length); + msync(str, length, MS_SYNC); + munmap(str, length); + + close(fd); + + return MAIL_NO_ERROR; +} + +int generic_cache_read(char * filename, char ** result, size_t * result_len) +{ + int fd; + char * str; + struct stat buf; + MMAPString * mmapstr; + char * content; + int res; + + if (stat(filename, &buf) < 0) { + res = MAIL_ERROR_CACHE_MISS; + goto err; + } + + fd = open(filename, O_RDONLY); + if (fd == -1) { + res = MAIL_ERROR_CACHE_MISS; + goto err; + } + + str = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (str == (char *)MAP_FAILED) { + res = MAIL_ERROR_FILE; + goto close; + } + + mmapstr = mmap_string_new_len(str, buf.st_size); + if (mmapstr == NULL) { + res = MAIL_ERROR_MEMORY; + goto unmap; + } + + if (mmap_string_ref(mmapstr) < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + content = mmapstr->str; + + munmap(str, buf.st_size); + close(fd); + + * result = content; + * result_len = buf.st_size; + + return MAIL_NO_ERROR; + + free: + mmap_string_free(mmapstr); + unmap: + munmap(str, buf.st_size); + close: + close(fd); + err: + return res; +} + +static int flags_extension_read(MMAPString * mmapstr, size_t * index, + clist ** result) +{ + clist * list; + int r; + uint32_t count; + uint32_t i; + int res; + + r = mailimf_cache_int_read(mmapstr, index, &count); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < count ; i++) { + char * str; + + r = mailimf_cache_string_read(mmapstr, index, &str); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, str); + if (r < 0) { + free(str); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + * result = list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + err: + return res; +} + +static int generic_flags_read(MMAPString * mmapstr, size_t * index, + struct mail_flags ** result) +{ + clist * ext; + int r; + struct mail_flags * flags; + uint32_t value; + int res; + + r = mailimf_cache_int_read(mmapstr, index, &value); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + ext = NULL; + r = flags_extension_read(mmapstr, index, &ext); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + flags = mail_flags_new(value, ext); + if (flags == NULL) { + res = r; + goto free; + } + + * result = flags; + + return MAIL_NO_ERROR; + + free: + clist_foreach(ext, (clist_func) free, NULL); + clist_free(ext); + err: + return res; +} + +static int flags_extension_write(MMAPString * mmapstr, size_t * index, + clist * ext) +{ + int r; + clistiter * cur; + + r = mailimf_cache_int_write(mmapstr, index, clist_count(ext)); + if (r != MAIL_NO_ERROR) + return r; + + for(cur = clist_begin(ext) ; cur != NULL ; cur = clist_next(cur)) { + char * ext_flag; + + ext_flag = clist_content(cur); + r = mailimf_cache_string_write(mmapstr, index, + ext_flag, strlen(ext_flag)); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + +static int generic_flags_write(MMAPString * mmapstr, size_t * index, + struct mail_flags * flags) +{ + int r; + + r = mailimf_cache_int_write(mmapstr, index, + flags->fl_flags & ~MAIL_FLAG_NEW); + if (r != MAIL_NO_ERROR) + return r; + + r = flags_extension_write(mmapstr, index, + flags->fl_extension); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + + + + +static struct mail_flags * mail_flags_dup(struct mail_flags * flags) +{ + clist * list; + struct mail_flags * new_flags; + int r; + clistiter * cur; + + list = clist_new(); + if (list == NULL) { + goto err; + } + + for(cur = clist_begin(flags->fl_extension) ; cur != NULL ; + cur = clist_next(cur)) { + char * ext; + char * original_ext; + + original_ext = clist_content(cur); + ext = strdup(original_ext); + if (ext == NULL) { + goto free; + } + + r = clist_append(list, ext); + if (r < 0) { + free(ext); + goto free; + } + } + + new_flags = mail_flags_new(flags->fl_flags, list); + if (new_flags == NULL) { + goto free; + } + + return new_flags; + + free: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + err: + return NULL; +} + +static mailmessage * mailmessage_build(mailmessage * msg) +{ + mailmessage * new_msg; + + new_msg = malloc(sizeof(* new_msg)); + if (new_msg == NULL) + goto err; + + new_msg->msg_session = msg->msg_session; + new_msg->msg_driver = msg->msg_driver; + new_msg->msg_index = msg->msg_index; + if (msg->msg_uid == NULL) + new_msg->msg_uid = NULL; + else { + new_msg->msg_uid = strdup(msg->msg_uid); + if (new_msg->msg_uid == NULL) + goto free; + } + + new_msg->msg_cached = msg->msg_cached; + new_msg->msg_size = msg->msg_size; + new_msg->msg_fields = NULL; + new_msg->msg_flags = mail_flags_dup(msg->msg_flags); + if (new_msg->msg_flags == NULL) { + free(new_msg->msg_uid); + goto free; + } + + new_msg->msg_mime = NULL; + new_msg->msg_data = NULL; + + return new_msg; + + free: + free(new_msg); + err: + return NULL; +} + +struct mail_flags_store * mail_flags_store_new(void) +{ + struct mail_flags_store * flags_store; + + flags_store = malloc(sizeof(struct mail_flags_store)); + if (flags_store == NULL) + goto err; + + flags_store->fls_tab = carray_new(128); + if (flags_store->fls_tab == NULL) + goto free; + + flags_store->fls_hash = chash_new(128, CHASH_COPYALL); + if (flags_store->fls_hash == NULL) + goto free_tab; + + return flags_store; + + free_tab: + carray_free(flags_store->fls_tab); + free: + free(flags_store); + err: + return NULL; +} + +void mail_flags_store_clear(struct mail_flags_store * flags_store) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) { + chashdatum key; + mailmessage * msg; + + msg = carray_get(flags_store->fls_tab, i); + + key.data = &msg->msg_index; + key.len = sizeof(msg->msg_index); + chash_delete(flags_store->fls_hash, &key, NULL); + + mailmessage_free(msg); + } + carray_set_size(flags_store->fls_tab, 0); +} + +void mail_flags_store_free(struct mail_flags_store * flags_store) +{ + mail_flags_store_clear(flags_store); + chash_free(flags_store->fls_hash); + carray_free(flags_store->fls_tab); + free(flags_store); +} + +int mail_flags_store_set(struct mail_flags_store * flags_store, + mailmessage * msg) +{ + chashdatum key; + chashdatum value; + unsigned int index; + int res; + int r; + mailmessage * new_msg; + + if (msg->msg_flags == NULL) { + res = MAIL_NO_ERROR; + goto err; + } + + /* duplicate needed message info */ + new_msg = mailmessage_build(msg); + if (new_msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + key.data = &new_msg->msg_index; + key.len = sizeof(new_msg->msg_index); + + r = chash_get(flags_store->fls_hash, &key, &value); + if (r == 0) { + mailmessage * old_msg; + + index = * (unsigned int *) value.data; + old_msg = carray_get(flags_store->fls_tab, index); + mailmessage_free(old_msg); + } + else { + r = carray_set_size(flags_store->fls_tab, + carray_count(flags_store->fls_tab) + 1); + if (r != 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + index = carray_count(flags_store->fls_tab) - 1; + } + + carray_set(flags_store->fls_tab, index, new_msg); + + value.data = &index; + value.len = sizeof(index); + + r = chash_set(flags_store->fls_hash, &key, &value, NULL); + if (r < 0) { + carray_delete(flags_store->fls_tab, index); + res = MAIL_ERROR_MEMORY; + goto free; + } + + return MAIL_NO_ERROR; + + free: + mailmessage_free(new_msg); + err: + return res; +} + +static int msg_index_compare(mailmessage ** msg1, mailmessage ** msg2) +{ + return (* msg1)->msg_index - (* msg2)->msg_index; +} + +void mail_flags_store_sort(struct mail_flags_store * flags_store) +{ + qsort(carray_data(flags_store->fls_tab), + carray_count(flags_store->fls_tab), sizeof(mailmessage *), + (int (*)(const void *, const void *)) msg_index_compare); +} + +struct mail_flags * +mail_flags_store_get(struct mail_flags_store * flags_store, uint32_t index) +{ + struct mail_flags * flags; + chashdatum key; + chashdatum value; + int r; + unsigned int tab_index; + mailmessage * msg; + + key.data = &index; + key.len = sizeof(index); + + r = chash_get(flags_store->fls_hash, &key, &value); + + if (r < 0) + return NULL; + +#if 0 + flags = mail_flags_dup((struct mail_flags *) value.data); +#endif + tab_index = * (unsigned int *) value.data; + msg = carray_get(flags_store->fls_tab, tab_index); + if (msg->msg_flags == NULL) + return NULL; + + flags = mail_flags_dup(msg->msg_flags); + + return flags; +} + +int mail_flags_compare(struct mail_flags * flags1, struct mail_flags * flags2) +{ + clistiter * cur1; + + if (clist_count(flags1->fl_extension) != clist_count(flags2->fl_extension)) + return -1; + + for(cur1 = clist_begin(flags1->fl_extension) ; cur1 != NULL ; + cur1 = clist_next(cur1)) { + char * flag1; + clistiter * cur2; + int found; + + flag1 = clist_content(cur1); + + found = 0; + for(cur2 = clist_begin(flags2->fl_extension) ; cur2 != NULL ; + cur2 = clist_next(cur2)) { + char * flag2; + + flag2 = clist_content(cur2); + + if (strcasecmp(flag1, flag2) == 0) { + found = 1; + break; + } + } + + if (!found) + return -1; + } + + return flags1->fl_flags - flags2->fl_flags; +} + +int generic_cache_fields_read(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mailimf_fields ** result) +{ + int r; + int res; + size_t cur_token; + struct mailimf_fields * fields; + void * data; + size_t data_len; + + r = mail_cache_db_get(cache_db, keyname, strlen(keyname), &data, &data_len); + if (r != 0) { + res = MAIL_ERROR_CACHE_MISS; + goto err; + } + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (mmap_string_append_len(mmapstr, data, data_len) == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mailimf_cache_fields_read(mmapstr, &cur_token, &fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = fields; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int generic_cache_fields_write(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mailimf_fields * fields) +{ + int r; + int res; + size_t cur_token; + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_cache_fields_write(mmapstr, &cur_token, fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mail_cache_db_put(cache_db, keyname, strlen(keyname), + mmapstr->str, mmapstr->len); + if (r != 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +int generic_cache_flags_read(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mail_flags ** result) +{ + int r; + int res; + size_t cur_token; + struct mail_flags * flags; + void * data; + size_t data_len; + + data = NULL; + data_len = 0; + r = mail_cache_db_get(cache_db, keyname, strlen(keyname), &data, &data_len); + if (r != 0) { + res = MAIL_ERROR_CACHE_MISS; + goto err; + } + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (mmap_string_append_len(mmapstr, data, data_len) == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + flags = NULL; + r = generic_flags_read(mmapstr, &cur_token, &flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + * result = flags; + + return MAIL_NO_ERROR; + + err: + return res; +} + +int generic_cache_flags_write(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mail_flags * flags) +{ + int r; + int res; + size_t cur_token; + + r = mail_serialize_clear(mmapstr, &cur_token); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = generic_flags_write(mmapstr, &cur_token, flags); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mail_cache_db_put(cache_db, keyname, strlen(keyname), + mmapstr->str, mmapstr->len); + if (r != 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +int generic_cache_delete(struct mail_cache_db * cache_db, + char * keyname) +{ + int r; + int res; + + r = mail_cache_db_del(cache_db, keyname, strlen(keyname)); + if (r != 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + Added: freeswitch/trunk/libs/libetpan/src/driver/tools/generic_cache.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/tools/generic_cache.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,109 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: generic_cache.h,v 1.17 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef GENERIC_CACHE_H + +#define GENERIC_CACHE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "generic_cache_types.h" +#include "mailmessage_types.h" +#include "chash.h" +#include "carray.h" +#include "mail_cache_db_types.h" + +int generic_cache_create_dir(char * dirname); + +int generic_cache_store(char * filename, char * content, size_t length); +int generic_cache_read(char * filename, char ** result, size_t * result_len); + +int generic_cache_fields_read(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mailimf_fields ** result); + +int generic_cache_fields_write(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mailimf_fields * fields); + +int generic_cache_flags_read(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mail_flags ** result); + +int generic_cache_flags_write(struct mail_cache_db * cache_db, + MMAPString * mmapstr, + char * keyname, struct mail_flags * flags); + +int generic_cache_delete(struct mail_cache_db * cache_db, char * keyname); + +#if 0 +int generic_cache_fields_read(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mailimf_fields ** result); + +int generic_cache_fields_write(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mailimf_fields * fields); + +int generic_cache_flags_read(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mail_flags ** result); + +int generic_cache_flags_write(DB * dbp, MMAPString * mmapstr, + char * keyname, struct mail_flags * flags); + +int generic_cache_delete(DB * dbp, char * keyname); +#endif + +struct mail_flags_store * mail_flags_store_new(void); + +void mail_flags_store_clear(struct mail_flags_store * flags_store); + +void mail_flags_store_free(struct mail_flags_store * flags_store); + +int mail_flags_store_set(struct mail_flags_store * flags_store, + mailmessage * msg); + +void mail_flags_store_sort(struct mail_flags_store * flags_store); + +struct mail_flags * +mail_flags_store_get(struct mail_flags_store * flags_store, uint32_t index); + +int mail_flags_compare(struct mail_flags * flags1, struct mail_flags * flags2); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/tools/generic_cache_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/tools/generic_cache_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: generic_cache_types.h,v 1.6 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef GENERIC_CACHE_TYPE_H + +#define GENERIC_CACHE_TYPE_H + +#include <libetpan/carray.h> +#include <libetpan/chash.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct mail_flags_store { + carray * fls_tab; + chash * fls_hash; +}; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/tools/imfcache.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/tools/imfcache.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1434 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imfcache.c,v 1.18 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "imfcache.h" + +#include <stdlib.h> +#include <string.h> + +static int mailimf_cache_field_write(MMAPString * mmapstr, size_t * index, + struct mailimf_field * field); +static int mailimf_cache_orig_date_write(MMAPString * mmapstr, size_t * index, + struct mailimf_orig_date * date); +static int mailimf_cache_date_time_write(MMAPString * mmapstr, size_t * index, + struct mailimf_date_time * date_time); +static int mailimf_cache_from_write(MMAPString * mmapstr, size_t * index, + struct mailimf_from * from); +static int mailimf_cache_sender_write(MMAPString * mmapstr, size_t * index, + struct mailimf_sender * sender); +static int mailimf_cache_reply_to_write(MMAPString * mmapstr, size_t * index, + struct mailimf_reply_to * reply_to); +static int mailimf_cache_to_write(MMAPString * mmapstr, size_t * index, + struct mailimf_to * to); +static int mailimf_cache_cc_write(MMAPString * mmapstr, size_t * index, + struct mailimf_cc * to); +static int mailimf_cache_bcc_write(MMAPString * mmapstr, size_t * index, + struct mailimf_bcc * to); +static int mailimf_cache_message_id_write(MMAPString * mmapstr, size_t * index, + struct mailimf_message_id * message_id); +static int mailimf_cache_msg_id_list_write(MMAPString * mmapstr, size_t * index, + clist * list); +static int mailimf_cache_in_reply_to_write(MMAPString * mmapstr, size_t * index, + struct mailimf_in_reply_to * + in_reply_to); +static int mailimf_cache_references_write(MMAPString * mmapstr, size_t * index, + struct mailimf_references * references); +static int mailimf_cache_subject_write(MMAPString * mmapstr, size_t * index, + struct mailimf_subject * subject); +static int mailimf_cache_address_list_write(MMAPString * mmapstr, + size_t * index, + struct mailimf_address_list * + addr_list); +static int mailimf_cache_address_write(MMAPString * mmapstr, size_t * index, + struct mailimf_address * addr); +static int mailimf_cache_group_write(MMAPString * mmapstr, size_t * index, + struct mailimf_group * group); +static int mailimf_cache_mailbox_list_write(MMAPString * mmapstr, + size_t * index, + struct mailimf_mailbox_list * mb_list); +static int mailimf_cache_mailbox_write(MMAPString * mmapstr, size_t * index, + struct mailimf_mailbox * mb); + + +static int mailimf_cache_field_read(MMAPString * mmapstr, size_t * index, + struct mailimf_field ** result); +static int mailimf_cache_orig_date_read(MMAPString * mmapstr, size_t * index, + struct mailimf_orig_date ** result); +static int mailimf_cache_date_time_read(MMAPString * mmapstr, size_t * index, + struct mailimf_date_time ** result); +static int mailimf_cache_from_read(MMAPString * mmapstr, size_t * index, + struct mailimf_from ** result); +static int mailimf_cache_sender_read(MMAPString * mmapstr, size_t * index, + struct mailimf_sender ** result); +static int mailimf_cache_reply_to_read(MMAPString * mmapstr, size_t * index, + struct mailimf_reply_to ** result); +static int mailimf_cache_to_read(MMAPString * mmapstr, size_t * index, + struct mailimf_to ** result); +static int mailimf_cache_cc_read(MMAPString * mmapstr, size_t * index, + struct mailimf_cc ** result); +static int mailimf_cache_bcc_read(MMAPString * mmapstr, size_t * index, + struct mailimf_bcc ** result); +static int mailimf_cache_message_id_read(MMAPString * mmapstr, size_t * index, + struct mailimf_message_id ** result); +static int mailimf_cache_msg_id_list_read(MMAPString * mmapstr, size_t * index, + clist ** result); +static int +mailimf_cache_in_reply_to_read(MMAPString * mmapstr, size_t * index, + struct mailimf_in_reply_to ** result); + +static int mailimf_cache_references_read(MMAPString * mmapstr, size_t * index, + struct mailimf_references ** result); +static int mailimf_cache_subject_read(MMAPString * mmapstr, size_t * index, + struct mailimf_subject ** result); +static int mailimf_cache_address_list_read(MMAPString * mmapstr, size_t * index, + struct mailimf_address_list ** result); +static int mailimf_cache_address_read(MMAPString * mmapstr, size_t * index, + struct mailimf_address ** result); +static int mailimf_cache_group_read(MMAPString * mmapstr, size_t * index, + struct mailimf_group ** result); +static int +mailimf_cache_mailbox_list_read(MMAPString * mmapstr, size_t * index, + struct mailimf_mailbox_list ** result); +static int mailimf_cache_mailbox_read(MMAPString * mmapstr, size_t * index, + struct mailimf_mailbox ** result); + +enum { + CACHE_NULL_POINTER = 0, + CACHE_NOT_NULL = 1 +}; + +int mail_serialize_clear(MMAPString * mmapstr, size_t * index) +{ + if (mmap_string_set_size(mmapstr, 0) == NULL) + return MAIL_ERROR_MEMORY; + + * index = 0; + + return MAIL_NO_ERROR; +} + +int mail_serialize_write(MMAPString * mmapstr, size_t * index, + char * buf, size_t size) +{ + if (mmap_string_append_len(mmapstr, buf, size) == NULL) + return MAIL_ERROR_MEMORY; + + * index = * index + size; + + return MAIL_NO_ERROR; +} + +int mail_serialize_read(MMAPString * mmapstr, size_t * index, + char * buf, size_t size) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token + size > mmapstr->len) + return MAIL_ERROR_STREAM; + + memcpy(buf, mmapstr->str + cur_token, size); + * index = cur_token + size; + + return MAIL_NO_ERROR; +} + +int mailimf_cache_int_write(MMAPString * mmapstr, size_t * index, + uint32_t value) +{ + unsigned char ch; + int r; + int i; + + for(i = 0 ; i < 4 ; i ++) { + ch = value % 256; + + r = mail_serialize_write(mmapstr, index, (char *) &ch, 1); + if (r != MAIL_NO_ERROR) + return r; + value /= 256; + } + + return MAIL_NO_ERROR; +} + +int mailimf_cache_int_read(MMAPString * mmapstr, size_t * index, + uint32_t * result) +{ + unsigned char ch; + uint32_t value; + int i; + int r; + + value = 0; + for(i = 0 ; i < 4 ; i ++) { + r = mail_serialize_read(mmapstr, index, (char *) &ch, 1); + if (r != MAIL_NO_ERROR) + return r; + value = value | ch << (i << 3); + } + + * result = value; + + return MAIL_NO_ERROR; +} + + +int mailimf_cache_string_write(MMAPString * mmapstr, size_t * index, + char * str, size_t length) +{ + int r; + + if (str == NULL) { + r = mailimf_cache_int_write(mmapstr, index, CACHE_NULL_POINTER); + if (r != MAIL_NO_ERROR) + return r; + } + else { + r = mailimf_cache_int_write(mmapstr, index, CACHE_NOT_NULL); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, length); + if (r != MAIL_NO_ERROR) + return r; + + if (length != 0) { + r = mail_serialize_write(mmapstr, index, str, length); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_FILE; + } + } + + return MAIL_NO_ERROR; +} + +int mailimf_cache_string_read(MMAPString * mmapstr, size_t * index, + char ** result) +{ + int r; + uint32_t length; + char * str; + uint32_t type; + + r = mailimf_cache_int_read(mmapstr, index, &type); + if (r != MAIL_NO_ERROR) + return r; + + if (type == CACHE_NULL_POINTER) { + str = NULL; + } + else { + r = mailimf_cache_int_read(mmapstr, index, &length); + if (r != MAIL_NO_ERROR) + return r; + + str = malloc(length + 1); + if (str == NULL) + return MAIL_ERROR_MEMORY; + + r = mail_serialize_read(mmapstr, index, str, length); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_FILE; + + str[length] = 0; + } + + * result = str; + + return MAIL_NO_ERROR; +} + +int mailimf_cache_fields_write(MMAPString * mmapstr, size_t * index, + struct mailimf_fields * fields) +{ + clistiter * cur; + int r; + + r = mailimf_cache_int_write(mmapstr, index, + clist_count(fields->fld_list)); + if (r != MAIL_NO_ERROR) + return r; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + r = mailimf_cache_field_write(mmapstr, index, clist_content(cur)); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + +int mailimf_cache_fields_read(MMAPString * mmapstr, size_t * index, + struct mailimf_fields ** result) +{ + clist * list; + int r; + uint32_t count; + uint32_t i; + struct mailimf_fields * fields; + int res; + + r = mailimf_cache_int_read(mmapstr, index, &count); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < count ; i++) { + struct mailimf_field * field; + + field = NULL; + r = mailimf_cache_field_read(mmapstr, index, &field); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, field); + if (r < 0) { + mailimf_field_free(field); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = fields; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + err: + return res; +} + + +static int mailimf_cache_field_write(MMAPString * mmapstr, size_t * index, + struct mailimf_field * field) +{ + int r; + + r = mailimf_cache_int_write(mmapstr, index, field->fld_type); + if (r != MAIL_NO_ERROR) + return r; + + switch (field->fld_type) { + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_cache_orig_date_write(mmapstr, index, + field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + r = mailimf_cache_from_write(mmapstr, index, + field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_cache_sender_write(mmapstr, index, + field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_cache_reply_to_write(mmapstr, index, + field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + r = mailimf_cache_to_write(mmapstr, index, + field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + r = mailimf_cache_cc_write(mmapstr, index, + field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + r = mailimf_cache_bcc_write(mmapstr, index, + field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_cache_message_id_write(mmapstr, index, + field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_cache_in_reply_to_write(mmapstr, index, + field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_cache_references_write(mmapstr, index, + field->fld_data.fld_references); + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_cache_subject_write(mmapstr, index, + field->fld_data.fld_subject); + break; + default: + r = 0; + break; + } + + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + + +static int mailimf_cache_field_read(MMAPString * mmapstr, size_t * index, + struct mailimf_field ** result) +{ + int r; + uint32_t type; + struct mailimf_orig_date * orig_date; + struct mailimf_from * from; + struct mailimf_sender * sender; + struct mailimf_to * to; + struct mailimf_reply_to * reply_to; + struct mailimf_cc * cc; + struct mailimf_bcc * bcc; + struct mailimf_message_id * message_id; + struct mailimf_in_reply_to * in_reply_to; + struct mailimf_references * references; + struct mailimf_subject * subject; + struct mailimf_field * field; + int res; + + orig_date = NULL; + from = NULL; + sender = NULL; + to = NULL; + reply_to = NULL; + cc = NULL; + bcc = NULL; + message_id = NULL; + in_reply_to = NULL; + references = NULL; + subject = NULL; + field = NULL; + + r = mailimf_cache_int_read(mmapstr, index, &type); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + switch (type) { + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_cache_orig_date_read(mmapstr, index, &orig_date); + break; + case MAILIMF_FIELD_FROM: + r = mailimf_cache_from_read(mmapstr, index, &from); + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_cache_sender_read(mmapstr, index, &sender); + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_cache_reply_to_read(mmapstr, index, &reply_to); + break; + case MAILIMF_FIELD_TO: + r = mailimf_cache_to_read(mmapstr, index, &to); + break; + case MAILIMF_FIELD_CC: + r = mailimf_cache_cc_read(mmapstr, index, &cc); + break; + case MAILIMF_FIELD_BCC: + r = mailimf_cache_bcc_read(mmapstr, index, &bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_cache_message_id_read(mmapstr, index, &message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_cache_in_reply_to_read(mmapstr, index, &in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_cache_references_read(mmapstr, index, &references); + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_cache_subject_read(mmapstr, index, &subject); + break; + default: + r = MAIL_ERROR_INVAL; + break; + } + + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, orig_date, from, sender, reply_to, + to, cc, bcc, message_id, + in_reply_to, references, + subject, NULL, NULL, NULL); + if (field == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + * result = field; + + return MAIL_NO_ERROR; + + free: + if (orig_date != NULL) + mailimf_orig_date_free(orig_date); + if (from != NULL) + mailimf_from_free(from); + if (sender != NULL) + mailimf_sender_free(sender); + if (reply_to != NULL) + mailimf_reply_to_free(reply_to); + if (to != NULL) + mailimf_to_free(to); + if (cc != NULL) + mailimf_cc_free(cc); + if (bcc != NULL) + mailimf_bcc_free(bcc); + if (message_id != NULL) + mailimf_message_id_free(message_id); + if (in_reply_to != NULL) + mailimf_in_reply_to_free(in_reply_to); + if (references != NULL) + mailimf_references_free(references); + if (subject != NULL) + mailimf_subject_free(subject); + err: + return res; +} + +static int mailimf_cache_orig_date_write(MMAPString * mmapstr, size_t * index, + struct mailimf_orig_date * date) +{ + return mailimf_cache_date_time_write(mmapstr, index, date->dt_date_time); +} + +static int mailimf_cache_orig_date_read(MMAPString * mmapstr, size_t * index, + struct mailimf_orig_date ** result) +{ + int r; + struct mailimf_date_time * date_time; + struct mailimf_orig_date * orig_date; + + r = mailimf_cache_date_time_read(mmapstr, index, &date_time); + if (r != MAIL_NO_ERROR) + return r; + + orig_date = mailimf_orig_date_new(date_time); + if (orig_date == NULL) { + mailimf_date_time_free(date_time); + return MAIL_ERROR_MEMORY; + } + + * result = orig_date; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_date_time_write(MMAPString * mmapstr, size_t * index, + struct mailimf_date_time * date_time) +{ + int r; + + r = mailimf_cache_int_write(mmapstr, index, date_time->dt_day); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, date_time->dt_month); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, date_time->dt_year); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, date_time->dt_hour); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, date_time->dt_min); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, date_time->dt_sec); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, date_time->dt_zone); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_date_time_read(MMAPString * mmapstr, size_t * index, + struct mailimf_date_time ** result) +{ + int r; + uint32_t day; + uint32_t month; + uint32_t year; + uint32_t hour; + uint32_t min; + uint32_t sec; + uint32_t zone; + struct mailimf_date_time * date_time; + + r = mailimf_cache_int_read(mmapstr, index, &day); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, index, &month); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, index, &year); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, index, &hour); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, index, &min); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, index, &sec); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_read(mmapstr, index, &zone); + if (r != MAIL_NO_ERROR) + return r; + + date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone); + if (date_time == NULL) + return MAIL_ERROR_MEMORY; + + * result = date_time; + + return MAIL_NO_ERROR; + +} + + +static int mailimf_cache_from_write(MMAPString * mmapstr, size_t * index, + struct mailimf_from * from) +{ + return mailimf_cache_mailbox_list_write(mmapstr, index, from->frm_mb_list); +} + +static int mailimf_cache_from_read(MMAPString * mmapstr, size_t * index, + struct mailimf_from ** result) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + int r; + + r = mailimf_cache_mailbox_list_read(mmapstr, index, &mb_list); + if (r != MAIL_NO_ERROR) + return r; + + from = mailimf_from_new(mb_list); + if (from == NULL) { + mailimf_mailbox_list_free(mb_list); + return MAIL_ERROR_MEMORY; + } + + * result = from; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_sender_write(MMAPString * mmapstr, size_t * index, + struct mailimf_sender * sender) +{ + return mailimf_cache_mailbox_write(mmapstr, index, sender->snd_mb); +} + +static int mailimf_cache_sender_read(MMAPString * mmapstr, size_t * index, + struct mailimf_sender ** result) +{ + int r; + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + + r = mailimf_cache_mailbox_read(mmapstr, index, &mb); + if (r != MAIL_NO_ERROR) + return r; + + sender = mailimf_sender_new(mb); + if (sender == NULL) { + mailimf_mailbox_free(mb); + return MAIL_ERROR_MEMORY; + } + + * result = sender; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_reply_to_write(MMAPString * mmapstr, size_t * index, + struct mailimf_reply_to * reply_to) +{ + return mailimf_cache_address_list_write(mmapstr, index, + reply_to->rt_addr_list); +} + +static int mailimf_cache_reply_to_read(MMAPString * mmapstr, size_t * index, + struct mailimf_reply_to ** result) +{ + int r; + struct mailimf_address_list * addr_list; + struct mailimf_reply_to * reply_to; + + r = mailimf_cache_address_list_read(mmapstr, index, &addr_list); + if (r != MAIL_NO_ERROR) + return r; + + reply_to = mailimf_reply_to_new(addr_list); + if (reply_to == NULL) { + mailimf_address_list_free(addr_list); + return MAIL_ERROR_MEMORY; + } + + * result = reply_to; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_to_write(MMAPString * mmapstr, size_t * index, + struct mailimf_to * to) +{ + return mailimf_cache_address_list_write(mmapstr, index, to->to_addr_list); +} + +static int mailimf_cache_to_read(MMAPString * mmapstr, size_t * index, + struct mailimf_to ** result) +{ + int r; + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + + r = mailimf_cache_address_list_read(mmapstr, index, &addr_list); + if (r != MAIL_NO_ERROR) + return r; + + to = mailimf_to_new(addr_list); + if (to == NULL) { + mailimf_address_list_free(addr_list); + return MAIL_ERROR_MEMORY; + } + + * result = to; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_cc_write(MMAPString * mmapstr, size_t * index, + struct mailimf_cc * cc) +{ + return mailimf_cache_address_list_write(mmapstr, index, cc->cc_addr_list); +} + +static int mailimf_cache_cc_read(MMAPString * mmapstr, size_t * index, + struct mailimf_cc ** result) +{ + int r; + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + + r = mailimf_cache_address_list_read(mmapstr, index, &addr_list); + if (r != MAIL_NO_ERROR) + return r; + + cc = mailimf_cc_new(addr_list); + if (cc == NULL) { + mailimf_address_list_free(addr_list); + return MAIL_ERROR_MEMORY; + } + + * result = cc; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_bcc_write(MMAPString * mmapstr, size_t * index, + struct mailimf_bcc * bcc) +{ + return mailimf_cache_address_list_write(mmapstr, index, bcc->bcc_addr_list); +} + +static int mailimf_cache_bcc_read(MMAPString * mmapstr, size_t * index, + struct mailimf_bcc ** result) +{ + int r; + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + + r = mailimf_cache_address_list_read(mmapstr, index, &addr_list); + if (r != MAIL_NO_ERROR) + return r; + + bcc = mailimf_bcc_new(addr_list); + if (bcc == NULL) { + mailimf_address_list_free(addr_list); + return MAIL_ERROR_MEMORY; + } + + * result = bcc; + + return MAIL_NO_ERROR; +} + +static int +mailimf_cache_message_id_write(MMAPString * mmapstr, size_t * index, + struct mailimf_message_id * message_id) +{ + return mailimf_cache_string_write(mmapstr, index, + message_id->mid_value, strlen(message_id->mid_value)); +} + +static int mailimf_cache_message_id_read(MMAPString * mmapstr, size_t * index, + struct mailimf_message_id ** result) +{ + struct mailimf_message_id * message_id; + char * str; + int r; + + r = mailimf_cache_string_read(mmapstr, index, &str); + if (r != MAIL_NO_ERROR) + return r; + + message_id = mailimf_message_id_new(str); + if (message_id == NULL) { + free(str); + return MAIL_ERROR_MEMORY; + } + + * result = message_id; + + return MAIL_NO_ERROR; +} + +static int +mailimf_cache_msg_id_list_write(MMAPString * mmapstr, size_t * index, + clist * list) +{ + clistiter * cur; + int r; + + r = mailimf_cache_int_write(mmapstr, index, clist_count(list)); + if (r != MAIL_NO_ERROR) + return r; + + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + char * msgid; + + msgid = clist_content(cur); + + r = mailimf_cache_string_write(mmapstr, index, msgid, strlen(msgid)); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_msg_id_list_read(MMAPString * mmapstr, size_t * index, + clist ** result) +{ + clist * list; + int r; + uint32_t count; + uint32_t i; + int res; + + r = mailimf_cache_int_read(mmapstr, index, &count); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < count ; i++) { + char * msgid; + + r = mailimf_cache_string_read(mmapstr, index, &msgid); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = clist_append(list, msgid); + if (r < 0) { + free(msgid); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + * result = list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) free, NULL); + clist_free(list); + err: + return res; +} + +static int +mailimf_cache_in_reply_to_write(MMAPString * mmapstr, size_t * index, + struct mailimf_in_reply_to * in_reply_to) +{ + return mailimf_cache_msg_id_list_write(mmapstr, index, + in_reply_to->mid_list); +} + +static int mailimf_cache_in_reply_to_read(MMAPString * mmapstr, size_t * index, + struct mailimf_in_reply_to ** result) +{ + int r; + clist * msg_id_list; + struct mailimf_in_reply_to * in_reply_to; + + r = mailimf_cache_msg_id_list_read(mmapstr, index, &msg_id_list); + if (r != MAIL_NO_ERROR) + return r; + + in_reply_to = mailimf_in_reply_to_new(msg_id_list); + if (in_reply_to == NULL) { + clist_foreach(msg_id_list, (clist_func) free, NULL); + clist_free(msg_id_list); + return MAIL_ERROR_MEMORY; + } + + * result = in_reply_to; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_references_write(MMAPString * mmapstr, size_t * index, + struct mailimf_references * references) +{ + return mailimf_cache_msg_id_list_write(mmapstr, index, + references->mid_list); +} + +static int mailimf_cache_references_read(MMAPString * mmapstr, size_t * index, + struct mailimf_references ** result) +{ + int r; + clist * msg_id_list; + struct mailimf_references * references; + + r = mailimf_cache_msg_id_list_read(mmapstr, index, &msg_id_list); + if (r != MAIL_NO_ERROR) + return r; + + references = mailimf_references_new(msg_id_list); + if (references == NULL) { + clist_foreach(msg_id_list, (clist_func) free, NULL); + clist_free(msg_id_list); + return MAIL_ERROR_MEMORY; + } + + * result = references; + + return MAIL_NO_ERROR; +} + + +static int mailimf_cache_subject_write(MMAPString * mmapstr, size_t * index, + struct mailimf_subject * subject) +{ + return mailimf_cache_string_write(mmapstr, index, + subject->sbj_value, strlen(subject->sbj_value)); +} + +static int mailimf_cache_subject_read(MMAPString * mmapstr, size_t * index, + struct mailimf_subject ** result) +{ + char * str; + struct mailimf_subject * subject; + int r; + + r = mailimf_cache_string_read(mmapstr, index, &str); + if (r != MAIL_NO_ERROR) + return r; + + if (str == NULL) { + str = strdup(""); + if (str == NULL) + return MAIL_ERROR_MEMORY; + } + + subject = mailimf_subject_new(str); + if (subject == NULL) { + free(str); + return MAIL_ERROR_MEMORY; + } + + * result = subject; + + return MAIL_NO_ERROR; +} + + +static int +mailimf_cache_address_list_write(MMAPString * mmapstr, size_t * index, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + + if (addr_list == NULL) { + r = mailimf_cache_int_write(mmapstr, index, CACHE_NULL_POINTER); + if (r != MAIL_NO_ERROR) + return r; + } + else { + r = mailimf_cache_int_write(mmapstr, index, CACHE_NOT_NULL); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, + clist_count(addr_list->ad_list)); + if (r != MAIL_NO_ERROR) + return r; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + r = mailimf_cache_address_write(mmapstr, index, addr); + if (r != MAIL_NO_ERROR) + return r; + } + } + + return MAIL_NO_ERROR; +} + +static int +mailimf_cache_address_list_read(MMAPString * mmapstr, size_t * index, + struct mailimf_address_list ** result) +{ + struct mailimf_address_list * addr_list; + uint32_t count; + uint32_t i; + int r; + clist * list; + int res; + uint32_t type; + + r = mailimf_cache_int_read(mmapstr, index, &type); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (type == CACHE_NULL_POINTER) { + * result = NULL; + return MAIL_NO_ERROR; + } + + r = mailimf_cache_int_read(mmapstr, index, &count); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < count ; i++) { + struct mailimf_address * addr; + + r = mailimf_cache_address_read(mmapstr, index, &addr); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, addr); + if (r < 0) { + mailimf_address_free(addr); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + addr_list = mailimf_address_list_new(list); + if (addr_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = addr_list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_address_free, NULL); + clist_free(list); + err: + return res; +} + +static int mailimf_cache_address_write(MMAPString * mmapstr, size_t * index, + struct mailimf_address * addr) +{ + int r; + + r = mailimf_cache_int_write(mmapstr, index, addr->ad_type); + if (r != MAIL_NO_ERROR) + return r; + + switch(addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = mailimf_cache_mailbox_write(mmapstr, index, addr->ad_data.ad_mailbox); + if (r != MAIL_NO_ERROR) + return r; + + break; + + case MAILIMF_ADDRESS_GROUP: + r = mailimf_cache_group_write(mmapstr, index, addr->ad_data.ad_group); + if (r != MAIL_NO_ERROR) + return r; + + break; + } + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_address_read(MMAPString * mmapstr, size_t * index, + struct mailimf_address ** result) +{ + uint32_t type; + int r; + struct mailimf_mailbox * mailbox; + struct mailimf_group * group; + struct mailimf_address * addr; + + r = mailimf_cache_int_read(mmapstr, index, &type); + if (r != MAIL_NO_ERROR) + return r; + + mailbox = NULL; + group = NULL; + + switch (type) { + case MAILIMF_ADDRESS_MAILBOX: + r = mailimf_cache_mailbox_read(mmapstr, index, &mailbox); + if (r != MAIL_NO_ERROR) + return r; + + break; + + case MAILIMF_ADDRESS_GROUP: + r = mailimf_cache_group_read(mmapstr, index, &group); + if (r != MAIL_NO_ERROR) + return r; + + break; + } + + addr = mailimf_address_new(type, mailbox, group); + if (addr == NULL) + goto free; + + * result = addr; + + return MAIL_NO_ERROR; + + free: + if (mailbox != NULL) + mailimf_mailbox_free(mailbox); + if (group != NULL) + mailimf_group_free(group); + return MAIL_ERROR_MEMORY; +} + +static int mailimf_cache_group_write(MMAPString * mmapstr, size_t * index, + struct mailimf_group * group) +{ + int r; + + r = mailimf_cache_string_write(mmapstr, index, group->grp_display_name, + strlen(group->grp_display_name)); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_mailbox_list_write(mmapstr, index, group->grp_mb_list); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_group_read(MMAPString * mmapstr, size_t * index, + struct mailimf_group ** result) +{ + int r; + char * display_name; + struct mailimf_mailbox_list * mb_list; + struct mailimf_group * group; + int res; + + r = mailimf_cache_string_read(mmapstr, index, &display_name); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_cache_mailbox_list_read(mmapstr, index, &mb_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_dsp_name; + } + + group = mailimf_group_new(display_name, mb_list); + if (group == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_mb_list; + } + + * result = group; + + return MAIL_NO_ERROR; + + free_mb_list: + mailimf_mailbox_list_free(mb_list); + free_dsp_name: + free(display_name); + err: + return res; +} + +static int +mailimf_cache_mailbox_list_write(MMAPString * mmapstr, size_t * index, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + + if (mb_list == NULL) { + r = mailimf_cache_int_write(mmapstr, index, CACHE_NULL_POINTER); + if (r != MAIL_NO_ERROR) + return r; + } + else { + r = mailimf_cache_int_write(mmapstr, index, CACHE_NOT_NULL); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_int_write(mmapstr, index, + clist_count(mb_list->mb_list)); + if (r != MAIL_NO_ERROR) + return r; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + r = mailimf_cache_mailbox_write(mmapstr, index, mb); + if (r != MAIL_NO_ERROR) + return r; + } + } + + return MAIL_NO_ERROR; +} + +static int +mailimf_cache_mailbox_list_read(MMAPString * mmapstr, size_t * index, + struct mailimf_mailbox_list ** result) +{ + clist * list; + int r; + uint32_t count; + uint32_t i; + struct mailimf_mailbox_list * mb_list; + int res; + uint32_t type; + + r = mailimf_cache_int_read(mmapstr, index, &type); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + if (type == CACHE_NULL_POINTER) { + * result = NULL; + return MAIL_NO_ERROR; + } + + r = mailimf_cache_int_read(mmapstr, index, &count); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + for(i = 0 ; i < count ; i++) { + struct mailimf_mailbox * mb; + + r = mailimf_cache_mailbox_read(mmapstr, index, &mb); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(list, mb); + if (r < 0) { + mailimf_mailbox_free(mb); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + + mb_list = mailimf_mailbox_list_new(list); + if (mb_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + * result = mb_list; + + return MAIL_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(list); + err: + return res; +} + +static int mailimf_cache_mailbox_write(MMAPString * mmapstr, size_t * index, + struct mailimf_mailbox * mb) +{ + int r; + + if (mb->mb_display_name) { + r = mailimf_cache_string_write(mmapstr, index, + mb->mb_display_name, strlen(mb->mb_display_name)); + if (r != MAIL_NO_ERROR) + return r; + } + else { + r = mailimf_cache_string_write(mmapstr, index, NULL, 0); + if (r != MAIL_NO_ERROR) + return r; + } + + r = mailimf_cache_string_write(mmapstr, index, + mb->mb_addr_spec, strlen(mb->mb_addr_spec)); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +static int mailimf_cache_mailbox_read(MMAPString * mmapstr, size_t * index, + struct mailimf_mailbox ** result) +{ + int r; + char * dsp_name; + char * addr_spec; + struct mailimf_mailbox * mb; + + dsp_name = NULL; + + r = mailimf_cache_string_read(mmapstr, index, &dsp_name); + if (r != MAIL_NO_ERROR) + return r; + + r = mailimf_cache_string_read(mmapstr, index, &addr_spec); + if (r != MAIL_NO_ERROR) + goto free_dsp_name; + + mb = mailimf_mailbox_new(dsp_name, addr_spec); + if (mb == NULL) + goto free_addr; + + * result = mb; + + return MAIL_NO_ERROR; + + free_addr: + free(addr_spec); + free_dsp_name: + if (dsp_name != NULL) + free(dsp_name); + return MAIL_ERROR_MEMORY; +} Added: freeswitch/trunk/libs/libetpan/src/driver/tools/imfcache.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/tools/imfcache.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,75 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: imfcache.h,v 1.9 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef IMFCACHE_H + +#define IMFCACHE_H + +#include <stdio.h> +#include "mailimf.h" +#include "maildriver_types.h" +#include "mmapstring.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mail_serialize_clear(MMAPString * mmapstr, size_t * index); + +int mail_serialize_write(MMAPString * mmapstr, size_t * index, + char * buf, size_t size); + +int mail_serialize_read(MMAPString * mmapstr, size_t * index, + char * buf, size_t size); + +int mailimf_cache_int_write(MMAPString * mmapstr, size_t * index, + uint32_t value); +int mailimf_cache_string_write(MMAPString * mmapstr, size_t * index, + char * str, size_t length); +int mailimf_cache_int_read(MMAPString * mmapstr, size_t * index, + uint32_t * result); +int mailimf_cache_string_read(MMAPString * mmapstr, size_t * index, + char ** result); + +int mailimf_cache_fields_write(MMAPString * mmapstr, size_t * index, + struct mailimf_fields * fields); +int mailimf_cache_fields_read(MMAPString * mmapstr, size_t * index, + struct mailimf_fields ** result); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/tools/mailthread.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/tools/mailthread.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1754 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailthread.c,v 1.28 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailthread.h" +#include "mailthread_types.h" + +#include <string.h> +#include <time.h> +#include <stdlib.h> +#include <ctype.h> + +#include "mail.h" +#include "chash.h" +#include "carray.h" +#include "clist.h" +#include "mailmessage.h" +#ifdef _MSC_VER +# include "win_etpan.h" +#endif + +/* SEB */ +#ifdef NO_MACROS +# define inline +#endif + +static inline char * get_msg_id(mailmessage * msg) +{ + if (msg->msg_single_fields.fld_message_id != NULL) + return msg->msg_single_fields.fld_message_id->mid_value; + else + return NULL; +} + +static inline clist * get_ref(mailmessage * msg) +{ + if (msg->msg_single_fields.fld_references != NULL) + return msg->msg_single_fields.fld_references->mid_list; + else + return NULL; +} + +static inline clist * get_in_reply_to(mailmessage * msg) +{ + if (msg->msg_single_fields.fld_in_reply_to != NULL) + return msg->msg_single_fields.fld_in_reply_to->mid_list; + else + return NULL; +} + +static inline int skip_subj_blob(char * subj, size_t * begin, + size_t length) +{ + /* subj-blob = "[" *BLOBCHAR "]" *WSP */ + size_t cur_token; + + cur_token = * begin; + + if (subj[cur_token] != '[') + return FALSE; + + cur_token ++; + + while (1) { + if (cur_token >= length) + return FALSE; + + if (subj[cur_token] == '[') + return FALSE; + + if (subj[cur_token] == ']') + break; + + cur_token ++; + } + + cur_token ++; + + while (1) { + if (cur_token >= length) + break; + + if (subj[cur_token] != ' ') + break; + + cur_token ++; + } + + * begin = cur_token; + + return TRUE; +} + +static inline int skip_subj_refwd(char * subj, size_t * begin, + size_t length) +{ + /* subj-refwd = ("re" / ("fw" ["d"])) *WSP [subj-blob] ":" */ + size_t cur_token; + int prefix; + + cur_token = * begin; + + prefix = FALSE; + if (length >= 3) { + if (strncasecmp(subj + cur_token, "fwd", 3) == 0) { + cur_token += 3; + prefix = TRUE; + } + } + if (!prefix) { + if (length >= 2) { + if (strncasecmp(subj + cur_token, "fw", 2) == 0) { + cur_token += 2; + prefix = TRUE; + } + else if (strncasecmp(subj + cur_token, "re", 2) == 0) { + cur_token += 2; + prefix = TRUE; + } + } + } + + if (!prefix) + return FALSE; + + while (1) { + if (cur_token >= length) + break; + + if (subj[cur_token] != ' ') + break; + + cur_token ++; + } + + skip_subj_blob(subj, &cur_token, length); + + if (subj[cur_token] != ':') + return FALSE; + + cur_token ++; + + * begin = cur_token; + + return TRUE; +} + +static inline int skip_subj_leader(struct mailmessage_tree * tree, + char * subj, size_t * begin, + size_t length) +{ + size_t cur_token; + + cur_token = * begin; + + /* subj-leader = (*subj-blob subj-refwd) / WSP */ + + if (subj[cur_token] == ' ') { + cur_token ++; + } + else { + while (cur_token < length) { + if (!skip_subj_blob(subj, &cur_token, length)) + break; + } + if (!skip_subj_refwd(subj, &cur_token, length)) + return FALSE; + tree->node_is_reply = TRUE; + } + + * begin = cur_token; + + return TRUE; +} + + +static char * extract_subject(char * default_from, + struct mailmessage_tree * tree, + char * str) +{ + char * subj; + char * cur; + char * write_pos; + size_t len; + size_t begin; + + char * decoded; + size_t cur_token; + + int do_repeat_5; + int do_repeat_6; + int r; + + /* + (1) Convert any RFC 2047 encoded-words in the subject to + UTF-8. + */ + + decoded = NULL; + + cur_token = 0; + r = mailmime_encoded_phrase_parse(default_from, str, strlen(str), + &cur_token, "utf-8", + &decoded); + + if (r == MAILIMF_NO_ERROR) { + subj = decoded; + } + else + subj = strdup(str); + + len = strlen(subj); + + /* + Convert all tabs and continuations to space. + Convert all multiple spaces to a single space. + */ + + cur = subj; + write_pos = subj; + while (* cur != '\0') { + int cont; + + switch (* cur) { + case '\t': + case '\r': + case '\n': + cont = TRUE; + + cur ++; + while (* cur && cont) { + switch (* cur) { + case '\t': + case '\r': + case '\n': + cont = TRUE; + break; + default: + cont = FALSE; + break; + } + cur ++; + } + + * write_pos = ' '; + write_pos ++; + + break; + + default: + * write_pos = * cur; + write_pos ++; + + cur ++; + + break; + } + } + * write_pos = '\0'; + + begin = 0; + + do { + do_repeat_6 = FALSE; + + /* + (2) Remove all trailing text of the subject that matches + the subj-trailer ABNF, repeat until no more matches are + possible. + */ + + while (len > 0) { + int chg; + + chg = FALSE; + + /* subj-trailer = "(fwd)" / WSP */ + if (subj[len - 1] == ' ') { + subj[len - 1] = '\0'; + len --; + } + else { + if (len < 5) + break; + + if (strncasecmp(subj + len - 5, "(fwd)", 5) != 0) + break; + + subj[len - 5] = '\0'; + len -= 5; + tree->node_is_reply = TRUE; + } + } + + do { + size_t saved_begin; + + do_repeat_5 = FALSE; + + /* + (3) Remove all prefix text of the subject that matches the + subj-leader ABNF. + */ + + if (skip_subj_leader(tree, subj, &begin, len)) + do_repeat_5 = TRUE; + + /* + (4) If there is prefix text of the subject that matches the + subj-blob ABNF, and removing that prefix leaves a non-empty + subj-base, then remove the prefix text. + */ + + saved_begin = begin; + if (skip_subj_blob(subj, &begin, len)) { + if (begin == len) { + /* this will leave a empty subject base */ + begin = saved_begin; + } + else + do_repeat_5 = TRUE; + } + + /* + (5) Repeat (3) and (4) until no matches remain. + Note: it is possible to defer step (2) until step (6), + but this requires checking for subj-trailer in step (4). + */ + + } + while (do_repeat_5); + + /* + (6) If the resulting text begins with the subj-fwd-hdr ABNF + and ends with the subj-fwd-trl ABNF, remove the + subj-fwd-hdr and subj-fwd-trl and repeat from step (2). + */ + + if (len >= 5) { + size_t saved_begin; + + saved_begin = begin; + if (strncasecmp(subj + begin, "[fwd:", 5) == 0) { + begin += 5; + + if (subj[len - 1] != ']') + saved_begin = begin; + else { + tree->node_is_reply = TRUE; + + subj[len - 1] = '\0'; + len --; + do_repeat_6 = TRUE; + } + } + } + + } + while (do_repeat_6); + + /* + (7) The resulting text is the "base subject" used in + threading. + */ + + /* convert to upper case */ + + cur = subj + begin; + write_pos = subj; + + while (* cur != '\0') { + * write_pos = (char) toupper((unsigned char) * cur); + cur ++; + write_pos ++; + } + * write_pos = '\0'; + + return subj; +} + +static int get_extracted_subject(char * default_from, + struct mailmessage_tree * tree, + char ** result) +{ + if (tree->node_msg->msg_single_fields.fld_subject != NULL) { + char * subj; + + subj = extract_subject(default_from, + tree, tree->node_msg->msg_single_fields.fld_subject->sbj_value); + if (subj == NULL) + return MAIL_ERROR_MEMORY; + + * result = subj; + + return MAIL_NO_ERROR; + } + + return MAIL_ERROR_SUBJECT_NOT_FOUND; +} + +static int get_thread_subject(char * default_from, + struct mailmessage_tree * tree, + char ** result) +{ + char * thread_subject; + int r; + unsigned int i; + + if (tree->node_msg != NULL) { + if (tree->node_msg->msg_fields != NULL) { + r = get_extracted_subject(default_from, tree, &thread_subject); + + if (r != MAIL_NO_ERROR) + return r; + + * result = thread_subject; + return MAIL_NO_ERROR; + } + } + + for(i = 0 ; i < carray_count(tree->node_children) ; i ++) { + struct mailmessage_tree * child; + + child = carray_get(tree->node_children, i); + + r = get_thread_subject(default_from, child, &thread_subject); + + switch (r) { + case MAIL_NO_ERROR: + * result = thread_subject; + return MAIL_NO_ERROR; + + case MAIL_ERROR_SUBJECT_NOT_FOUND: + /* do nothing */ + break; + + default: + return r; + } + } + + return MAIL_ERROR_SUBJECT_NOT_FOUND; +} + + + +#ifndef WRONG +#define WRONG (-1) +#endif /* !defined WRONG */ + +static int tmcomp(struct tm * atmp, struct tm * btmp) +{ + register int result; + + if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && + (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && + (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && + (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && + (result = (atmp->tm_min - btmp->tm_min)) == 0) + result = atmp->tm_sec - btmp->tm_sec; + return result; +} + +static time_t mkgmtime(struct tm * tmp) +{ + register int dir; + register int bits; + register int saved_seconds; + time_t t; + struct tm yourtm, mytm; + + yourtm = *tmp; + saved_seconds = yourtm.tm_sec; + yourtm.tm_sec = 0; + /* + ** Calculate the number of magnitude bits in a time_t + ** (this works regardless of whether time_t is + ** signed or unsigned, though lint complains if unsigned). + */ + for (bits = 0, t = 1; t > 0; ++bits, t <<= 1) + ; + /* + ** If time_t is signed, then 0 is the median value, + ** if time_t is unsigned, then 1 << bits is median. + */ + t = (t < 0) ? 0 : ((time_t) 1 << bits); + for ( ; ; ) { + gmtime_r(&t, &mytm); + dir = tmcomp(&mytm, &yourtm); + if (dir != 0) { + if (bits-- < 0) + return WRONG; + if (bits < 0) + --t; + else if (dir > 0) + t -= (time_t) 1 << bits; + else t += (time_t) 1 << bits; + continue; + } + break; + } + t += saved_seconds; + return t; +} + +static inline time_t get_date(mailmessage * msg) +{ + struct tm tmval; + time_t timeval; + struct mailimf_date_time * date_time; + + if (msg->msg_single_fields.fld_orig_date == NULL) + return (time_t) -1; + + date_time = msg->msg_single_fields.fld_orig_date->dt_date_time; + + tmval.tm_sec = date_time->dt_sec; + tmval.tm_min = date_time->dt_min; + tmval.tm_hour = date_time->dt_hour; + tmval.tm_sec = date_time->dt_sec; + tmval.tm_mday = date_time->dt_day; + tmval.tm_mon = date_time->dt_month - 1; + tmval.tm_year = date_time->dt_year - 1900; + + timeval = mkgmtime(&tmval); + + timeval -= date_time->dt_zone * 36; + + return timeval; +} + +static inline int is_descendant(struct mailmessage_tree * node, + struct mailmessage_tree * maybe_child) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(node->node_children) ; i++) { + struct mailmessage_tree * tree; + + tree = carray_get(node->node_children, i); + if (tree == maybe_child) + return TRUE; + if (carray_count(tree->node_children) != 0) + if (is_descendant(tree, maybe_child)) + return TRUE; + } + + return FALSE; +} + +static int delete_dummy(carray * rootlist, carray * sibling_list, + unsigned int cur, unsigned int * pnext) +{ + struct mailmessage_tree * env_tree; + int res; + int r; + unsigned int cur_child; + unsigned int next; + + env_tree = carray_get(sibling_list, cur); + + cur_child = 0; + while (cur_child < carray_count(env_tree->node_children)) { + delete_dummy(rootlist, env_tree->node_children, cur_child, &cur_child); + } + + if (env_tree->node_msg == NULL) { + if (carray_count(env_tree->node_children) == 0) { + + /* If it is a dummy message with NO children, delete it. */ + mailmessage_tree_free(env_tree); + carray_delete(sibling_list, cur); + next = cur; + } + else { + /* If it is a dummy message with children, delete it, but + promote its children to the current level. */ + + /* + Do not promote the children if doing so would make them + children of the root, unless there is only one child. + */ + + cur_child = 0; + if ((sibling_list != rootlist) || + (carray_count(env_tree->node_children) == 1)) { + while (cur_child < carray_count(env_tree->node_children)) { + struct mailmessage_tree * child; + + child = carray_get(env_tree->node_children, cur_child); + r = carray_add(sibling_list, child, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + /* set new parent of the children */ + child->node_parent = env_tree->node_parent; + + carray_delete(env_tree->node_children, cur_child); + } + mailmessage_tree_free(env_tree); + carray_delete(sibling_list, cur); + next = cur; + } + else + next = cur + 1; + } + } + else + next = cur + 1; + + * pnext = next; + + return MAIL_NO_ERROR; + + err: + return res; +} + +static inline time_t tree_get_date(struct mailmessage_tree * tree) +{ + if (tree->node_msg != NULL) { + return tree->node_date; + } + else { + struct mailmessage_tree * subtree; + + if (carray_count(tree->node_children) == 0) + return (time_t) -1; + + subtree = carray_get(tree->node_children, 0); + + return subtree->node_date; + } +} + +static inline uint32_t tree_get_index(struct mailmessage_tree * tree) +{ + if (tree->node_msg == NULL) + return 0; + + return tree->node_msg->msg_index; +} + +int mailthread_tree_timecomp(struct mailmessage_tree ** ptree1, + struct mailmessage_tree ** ptree2) +{ + time_t date1; + time_t date2; + + date1 = tree_get_date(* ptree1); + date2 = tree_get_date(* ptree2); + + if ((date1 == (time_t) -1) || (date2 == (time_t) -1)) { + uint32_t index1; + uint32_t index2; + + index1 = tree_get_index(* ptree1); + index2 = tree_get_index(* ptree2); + return (int) ((long) index1 - (long) index2); + } + + return (int) ((long) date1 - (long) date2); +} + +static int tree_subj_time_comp(struct mailmessage_tree ** ptree1, + struct mailmessage_tree ** ptree2) +{ + char * subj1; + char * subj2; + time_t date1; + time_t date2; + int r; + + subj1 = (* ptree1)->node_base_subject; + subj2 = (* ptree2)->node_base_subject; + + if ((subj1 != NULL) && (subj2 != NULL)) + r = strcmp(subj1, subj2); + else { + if ((subj1 == NULL) && (subj2 == NULL)) + r = 0; + else if (subj1 == NULL) + r = -1; + else /* subj2 == NULL */ + r = 1; + } + + if (r != 0) + return r; + + date1 = (* ptree1)->node_date; + date2 = (* ptree2)->node_date; + + if ((date1 == (time_t) -1) || (date2 == (time_t) -1)) + return ((int32_t) (* ptree1)->node_msg->msg_index) - + ((int32_t) (* ptree2)->node_msg->msg_index); + + return (int) ((long) date1 - (long) date2); +} + + + +int mail_thread_sort(struct mailmessage_tree * tree, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **), + int sort_sub) +{ + unsigned int cur; + int r; + int res; + + for(cur = 0 ; cur < carray_count(tree->node_children) ; cur ++) { + struct mailmessage_tree * subtree; + + subtree = carray_get(tree->node_children, cur); + + if (sort_sub) { + r = mail_thread_sort(subtree, comp_func, sort_sub); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + } + + qsort(carray_data(tree->node_children), carray_count(tree->node_children), + sizeof(struct mailmessage_tree *), + (int (*)(const void *, const void *)) comp_func); + + return MAIL_NO_ERROR; + + err: + return res; +} + + +static int +mail_build_thread_references(char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int use_subject, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)) +{ + int r; + int res; + chash * msg_id_hash; + unsigned int cur; + struct mailmessage_tree * root; + carray * rootlist; + carray * msg_list; + unsigned int i; + chash * subject_hash; + + msg_id_hash = chash_new(128, CHASH_COPYNONE); + if (msg_id_hash == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + root = mailmessage_tree_new(NULL, (time_t) -1, NULL); + if (root == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_hash; + } + rootlist = root->node_children; + + msg_list = carray_new(128); + if (msg_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_root; + } + + /* collect message-ID */ + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + char * msgid; + struct mailmessage_tree * env_tree; + chashdatum hashkey; + chashdatum hashdata; + chashdatum hashold; + time_t date; + + msg = carray_get(env_list->msg_tab, i); + + if (msg == NULL) + continue; + + if (msg->msg_fields != NULL) { + msgid = get_msg_id(msg); + + if (msgid == NULL) { + msgid = mailimf_get_message_id(); + } + else { + hashkey.data = msgid; + hashkey.len = strlen(msgid); + + if (chash_get(msg_id_hash, &hashkey, &hashdata) == 0) + msgid = mailimf_get_message_id(); + else + msgid = strdup(msgid); + } + + if (msgid == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + date = get_date(msg); + + env_tree = mailmessage_tree_new(msgid, date, msg); + if (env_tree == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = carray_add(msg_list, env_tree, NULL); + if (r < 0) { + mailmessage_tree_free(env_tree); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + hashkey.data = msgid; + hashkey.len = strlen(msgid); + + hashdata.data = env_tree; + hashdata.len = 0; + + r = chash_set(msg_id_hash, &hashkey, &hashdata, &hashold); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + + /* (1) for all messages */ + + for(cur = 0 ; cur < carray_count(msg_list) ; cur ++) { + struct mailmessage_tree * env_tree; + mailmessage * msg; + clist * ref; + + env_tree = carray_get(msg_list, cur); + + msg = env_tree->node_msg; + + ref = NULL; + if (msg != NULL) { + ref = get_ref(msg); + if (ref == NULL) + ref = get_in_reply_to(msg); + } + + /* (A) Using the Message IDs in the message's references, link + the corresponding messages (those whose Message-ID header + line contains the given reference Message ID) together as + parent/child. + */ + + if (ref != NULL) { + /* try to start a tree */ + + clistiter * cur_ref; + chashdatum hashkey; + chashdatum hashdata; + chashdatum hashold; + struct mailmessage_tree * env_cur_tree; + struct mailmessage_tree * last_env_cur_tree; + + env_cur_tree = NULL; + for(cur_ref = clist_begin(ref) ; cur_ref != NULL ; + cur_ref = clist_next(cur_ref)) { + char * msgid; + + last_env_cur_tree = env_cur_tree; + + msgid = clist_content(cur_ref); + + hashkey.data = msgid; + hashkey.len = strlen(msgid); + + r = chash_get(msg_id_hash, &hashkey, &hashdata); + if (r < 0) { + /* not found, create a dummy message */ + msgid = strdup(msgid); + if (msgid == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + env_cur_tree = mailmessage_tree_new(msgid, (time_t) -1, NULL); + if (env_cur_tree == NULL) { + free(msgid); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + r = carray_add(msg_list, env_cur_tree, NULL); + if (r < 0) { + mailmessage_tree_free(env_cur_tree); + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + hashkey.data = msgid; + hashkey.len = strlen(msgid); + + hashdata.data = env_cur_tree; + hashdata.len = 0; + + r = chash_set(msg_id_hash, &hashkey, &hashdata, &hashold); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + else { + env_cur_tree = hashdata.data; + } + + if (last_env_cur_tree != NULL) { + if (env_cur_tree->node_parent == NULL) { + /* make it one child */ + if (env_cur_tree != last_env_cur_tree) { + if (!is_descendant(env_cur_tree, last_env_cur_tree)) { + /* set parent */ + env_cur_tree->node_parent = last_env_cur_tree; + r = carray_add(last_env_cur_tree->node_children, + env_cur_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + } + } + } + + /* (B) Create a parent/child link between the last reference + (or NIL if there are no references) and the current message. + If the current message already has a parent, it is probably + the result of a truncated References header line, so break + the current parent/child link before creating the new + correct one. + */ + + last_env_cur_tree = env_cur_tree; + + if (last_env_cur_tree != NULL) { + if (env_tree->node_parent == NULL) { + if (last_env_cur_tree != env_tree) { + if (!is_descendant(env_tree, last_env_cur_tree)) { + /* set parent */ + env_tree->node_parent = last_env_cur_tree; + r = carray_add(last_env_cur_tree->node_children, env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + } + } + } + } + } + } + + chash_free(msg_id_hash); + msg_id_hash = NULL; + + /* (2) Gather together all of the messages that have no parents + and make them all children (siblings of one another) of a dummy + parent (the "root"). + */ + + for(cur = 0 ; cur < carray_count(msg_list) ; cur ++) { + struct mailmessage_tree * env_tree; + + env_tree = carray_get(msg_list, cur); + if (env_tree->node_parent == NULL) { + r = carray_add(rootlist, env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + /* set parent */ + env_tree->node_parent = root; + } + } + + carray_free(msg_list); + msg_list = NULL; + + /* (3) Prune dummy messages from the thread tree. + */ + + cur = 0; + while (cur < carray_count(rootlist)) { + r = delete_dummy(rootlist, rootlist, cur, &cur); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + } + + /* (4) Sort the messages under the root (top-level siblings only) + by sent date. + */ + + r = mail_thread_sort(root, mailthread_tree_timecomp, FALSE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + if (use_subject) { + + /* (5) Gather together messages under the root that have the same + extracted subject text. + + (A) Create a table for associating extracted subjects with + messages. + */ + + subject_hash = chash_new(128, CHASH_COPYVALUE); + if (subject_hash == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_list; + } + + /* + (B) Populate the subject table with one message per + extracted subject. For each child of the root: + */ + + for(cur = 0 ; cur < carray_count(rootlist) ; cur ++) { + struct mailmessage_tree * env_tree; + chashdatum key; + chashdatum data; + char * base_subject; + int r; + + env_tree = carray_get(rootlist, cur); + + /* + (i) Find the subject of this thread by extracting the + base subject from the current message, or its first child + if the current message is a dummy. + */ + + r = get_thread_subject(default_from, env_tree, &base_subject); + + /* + (ii) If the extracted subject is empty, skip this + message. + */ + + if (r == MAIL_ERROR_SUBJECT_NOT_FOUND) { + /* no subject found */ + continue; + } + else if (r == MAIL_NO_ERROR) { + if (* base_subject == '\0') { + /* subject empty */ + free(base_subject); + continue; + } + else { + /* do nothing */ + } + } + else { + res = r; + goto free_subject_hash; + } + + env_tree->node_base_subject = base_subject; + + /* + (iii) Lookup the message associated with this extracted + subject in the table. + */ + + key.data = base_subject; + key.len = strlen(base_subject); + + r = chash_get(subject_hash, &key, &data); + + if (r < 0) { + /* + (iv) If there is no message in the table with this + subject, add the current message and the extracted + subject to the subject table. + */ + + data.data = &cur; + data.len = sizeof(cur); + + r = chash_set(subject_hash, &key, &data, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + } + else { + /* + Otherwise, replace the message in the table with the + current message if the message in the table is not a + dummy AND either of the following criteria are true: + The current message is a dummy, OR + The message in the table is a reply or forward (its + original subject contains a subj-refwd part and/or a + "(fwd)" subj-trailer) and the current message is not. + */ + struct mailmessage_tree * msg_in_table; + unsigned int * iter_in_table; + int replace; + + iter_in_table = data.data; + msg_in_table = carray_get(rootlist, cur); + + replace = FALSE; + /* message is dummy if info is NULL */ + if (msg_in_table->node_msg != NULL) { + + if (env_tree->node_msg == NULL) + replace = TRUE; + else { + if (env_tree->node_is_reply && !env_tree->node_is_reply) + replace = TRUE; + } + } + + if (replace) { + data.data = &cur; + data.len = sizeof(cur); + + r = chash_set(subject_hash, &key, &data, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + } + } + } + + /* + (C) Merge threads with the same subject. For each child of + the root: + */ + + cur = 0; + while (cur < carray_count(rootlist)) { + struct mailmessage_tree * env_tree; + chashdatum key; + chashdatum data; + int r; + struct mailmessage_tree * main_tree; + unsigned int * main_cur; + + env_tree = carray_get(rootlist, cur); + + if (env_tree == NULL) + goto next_msg; + + /* + (i) Find the subject of this thread as in step 4.B.i + above. + */ + + /* already done in tree->node_base_subject */ + + /* + (ii) If the extracted subject is empty, skip this + message. + */ + + if (env_tree->node_base_subject == NULL) + goto next_msg; + + if (* env_tree->node_base_subject == '\0') + goto next_msg; + + /* + (iii) Lookup the message associated with this extracted + subject in the table. + */ + + key.data = env_tree->node_base_subject; + key.len = strlen(env_tree->node_base_subject); + + r = chash_get(subject_hash, &key, &data); + if (r < 0) + goto next_msg; + + /* + (iv) If the message in the table is the current message, + skip this message. + */ + + main_cur = data.data; + if (* main_cur == cur) + goto next_msg; + + /* + Otherwise, merge the current message with the one in the + table using the following rules: + */ + + main_tree = carray_get(rootlist, * main_cur); + + /* + If both messages are dummies, append the current + message's children to the children of the message in + the table (the children of both messages become + siblings), and then delete the current message. + */ + + if ((env_tree->node_msg == NULL) && (main_tree->node_msg == NULL)) { + unsigned int old_size; + + old_size = carray_count(main_tree->node_children); + + r = carray_set_size(main_tree->node_children, old_size + + carray_count(env_tree->node_children)); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + + for(i = 0 ; i < carray_count(env_tree->node_children) ; i ++) { + struct mailmessage_tree * child; + + child = carray_get(env_tree->node_children, i); + carray_set(main_tree->node_children, old_size + i, child); + /* set parent */ + child->node_parent = main_tree; + } + carray_set_size(env_tree->node_children, 0); + /* this is the only case where children can be NULL, + this is before freeing it */ + mailmessage_tree_free(env_tree); + carray_delete_fast(rootlist, cur); + } + + /* + If the message in the table is a dummy and the current + message is not, make the current message a child of + the message in the table (a sibling of it's children). + */ + + else if (main_tree->node_msg == NULL) { + r = carray_add(main_tree->node_children, env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + /* set parent */ + env_tree->node_parent = main_tree; + + carray_delete_fast(rootlist, cur); + } + + /* + If the current message is a reply or forward and the + message in the table is not, make the current message + a child of the message in the table (a sibling of it's + children). + */ + + else if (env_tree->node_is_reply && !main_tree->node_is_reply) { + r = carray_add(main_tree->node_children, env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + /* set parent */ + env_tree->node_parent = main_tree; + + carray_delete_fast(rootlist, cur); + } + + /* + Otherwise, create a new dummy message and make both + the current message and the message in the table + children of the dummy. Then replace the message in + the table with the dummy message. + Note: Subject comparisons are case-insensitive, as + described under "Internationalization + Considerations." + */ + + else { + struct mailmessage_tree * new_main_tree; + char * base_subject; + unsigned int last; + + new_main_tree = mailmessage_tree_new(NULL, (time_t) -1, NULL); + if (new_main_tree == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + + /* main_tree->node_base_subject is never NULL */ + + base_subject = strdup(main_tree->node_base_subject); + if (base_subject == NULL) { + mailmessage_tree_free(new_main_tree); + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + + new_main_tree->node_base_subject = base_subject; + + r = carray_add(rootlist, new_main_tree, &last); + if (r < 0) { + mailmessage_tree_free(new_main_tree); + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + + r = carray_add(new_main_tree->node_children, main_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + /* set parent */ + main_tree->node_parent = new_main_tree; + + carray_delete_fast(rootlist, * main_cur); + + r = carray_add(new_main_tree->node_children, env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + /* set parent */ + env_tree->node_parent = new_main_tree; + + carray_delete_fast(rootlist, cur); + + data.data = &last; + data.len = sizeof(last); + + r = chash_set(subject_hash, &key, &data, NULL); + + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free_subject_hash; + } + } + + continue; + + next_msg: + cur ++; + continue; + } + + i = 0; + for(cur = 0 ; cur < carray_count(rootlist) ; cur ++) { + struct mailmessage_tree * env_tree; + + env_tree = carray_get(rootlist, cur); + if (env_tree == NULL) + continue; + + carray_set(rootlist, i, env_tree); + i ++; + } + carray_set_size(rootlist, i); + + chash_free(subject_hash); + } + + /* + (6) Traverse the messages under the root and sort each set of + siblings by sent date. Traverse the messages in such a way + that the "youngest" set of siblings are sorted first, and the + "oldest" set of siblings are sorted last (grandchildren are + sorted before children, etc). + + In the case of an exact match on + sent date or if either of the Date: headers used in a + comparison can not be parsed, use the order in which the + messages appear in the mailbox (that is, by sequence number) to + determine the order. In the case of a dummy message (which can + only occur with top-level siblings), use its first child for + sorting. + */ + +#if 0 + if (comp_func != NULL) { + r = mail_thread_sort(root, comp_func, TRUE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + } +#endif + if (comp_func == NULL) + comp_func = mailthread_tree_timecomp; + + r = mail_thread_sort(root, comp_func, TRUE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_list; + } + + * result = root; + + return MAIL_NO_ERROR; + + free_subject_hash: + chash_free(subject_hash); + free_list: + if (msg_list != NULL) { + for(i = 0 ; i < carray_count(msg_list) ; i ++) + mailmessage_tree_free(carray_get(msg_list, i)); + carray_free(msg_list); + } + free_root: + mailmessage_tree_free_recursive(root); + free_hash: + if (msg_id_hash != NULL) + chash_free(msg_id_hash); + err: + return res; +} + + + +static int +mail_build_thread_orderedsubject(char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)) +{ + unsigned int i; + carray * rootlist; + unsigned int cur; + struct mailmessage_tree * root; + int res; + int r; + struct mailmessage_tree * current_thread; + + root = mailmessage_tree_new(NULL, (time_t) -1, NULL); + if (root == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + rootlist = root->node_children; + + /* + The ORDEREDSUBJECT threading algorithm is also referred to as + "poor man's threading." + */ + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailmessage_tree * env_tree; + char * base_subject; + time_t date; + + msg = carray_get(env_list->msg_tab, i); + + if (msg == NULL) + continue; + + if (msg->msg_fields != NULL) { + + date = get_date(msg); + + env_tree = mailmessage_tree_new(NULL, date, msg); + if (env_tree == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + /* set parent */ + env_tree->node_parent = root; + r = carray_add(rootlist, env_tree, NULL); + if (r < 0) { + mailmessage_tree_free(env_tree); + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = get_extracted_subject(default_from, env_tree, &base_subject); + switch (r) { + case MAIL_NO_ERROR: + env_tree->node_base_subject = base_subject; + break; + + case MAIL_ERROR_SUBJECT_NOT_FOUND: + break; + + default: + res = r; + goto free; + } + } + } + + /* + The searched messages are sorted by + subject and then by the sent date. + */ + + r = mail_thread_sort(root, tree_subj_time_comp, FALSE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + /* + The messages are then split + into separate threads, with each thread containing messages + with the same extracted subject text. + */ + + current_thread = NULL; + + cur = 0; + while (cur < carray_count(rootlist)) { + struct mailmessage_tree * cur_env_tree; + + cur_env_tree = carray_get(rootlist, cur); + if (current_thread == NULL) { + current_thread = cur_env_tree; + cur ++; + continue; + } + + if ((cur_env_tree->node_base_subject == NULL) || + (current_thread->node_base_subject == NULL)) { + current_thread = cur_env_tree; + cur ++; + continue; + } + + if (strcmp(cur_env_tree->node_base_subject, + current_thread->node_base_subject) == 0) { + + /* set parent */ + cur_env_tree->node_parent = current_thread; + r = carray_add(current_thread->node_children, cur_env_tree, NULL); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + carray_delete(rootlist, cur); + } + else + cur ++; + current_thread = cur_env_tree; + } + + /* + Finally, the threads are + sorted by the sent date of the first message in the thread. + Note that each message in a thread is a child (as opposed to a + sibling) of the previous message. + */ + +#if 0 + if (comp_func != NULL) { + r = mail_thread_sort(root, comp_func, FALSE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + } +#endif + + if (comp_func == NULL) + comp_func = mailthread_tree_timecomp; + + r = mail_thread_sort(root, comp_func, FALSE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + * result = root; + + return MAIL_NO_ERROR; + + free: + mailmessage_tree_free_recursive(root); + err: + return res; +} + + +static int +mail_build_thread_none(char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)) +{ + unsigned int i; + carray * rootlist; + struct mailmessage_tree * root; + int res; + int r; + + root = mailmessage_tree_new(NULL, (time_t) -1, NULL); + if (root == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + rootlist = root->node_children; + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct mailmessage_tree * env_tree; + char * base_subject; + time_t date; + + msg = carray_get(env_list->msg_tab, i); + + if (msg == NULL) + continue; + + if (msg->msg_fields != NULL) { + + date = get_date(msg); + + env_tree = mailmessage_tree_new(NULL, date, msg); + if (env_tree == NULL) { + res = MAIL_ERROR_MEMORY; + goto free; + } + + /* set parent */ + env_tree->node_parent = root; + r = carray_add(rootlist, env_tree, NULL); + if (r < 0) { + mailmessage_tree_free(env_tree); + res = MAIL_ERROR_MEMORY; + goto free; + } + + r = get_extracted_subject(default_from, env_tree, &base_subject); + switch (r) { + case MAIL_NO_ERROR: + env_tree->node_base_subject = base_subject; + break; + + case MAIL_ERROR_SUBJECT_NOT_FOUND: + break; + + default: + res = r; + goto free; + } + } + } + + if (comp_func == NULL) + comp_func = mailthread_tree_timecomp; + + r = mail_thread_sort(root, comp_func, FALSE); + if (r != MAIL_NO_ERROR) { + res = r; + goto free; + } + + * result = root; + + return MAIL_NO_ERROR; + + free: + mailmessage_tree_free_recursive(root); + err: + return res; +} + + +int mail_build_thread(int type, char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) + mailmessage_resolve_single_fields(carray_get(env_list->msg_tab, i)); + + switch (type) { + case MAIL_THREAD_REFERENCES: + return mail_build_thread_references(default_from, + env_list, result, TRUE, comp_func); + + case MAIL_THREAD_REFERENCES_NO_SUBJECT: + return mail_build_thread_references(default_from, + env_list, result, FALSE, comp_func); + + case MAIL_THREAD_ORDEREDSUBJECT: + return mail_build_thread_orderedsubject(default_from, + env_list, result, comp_func); + + case MAIL_THREAD_NONE: + return mail_build_thread_none(default_from, + env_list, result, comp_func); + + default: + return MAIL_ERROR_NOT_IMPLEMENTED; + } +} Added: freeswitch/trunk/libs/libetpan/src/driver/tools/mailthread.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/tools/mailthread.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,108 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailthread.h,v 1.14 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef MAILTHREAD_H + +#define MAILTHREAD_H + +#include <libetpan/mailthread_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + mail_build_thread constructs a tree with the message using the + given style. + + @param type is the type of threading to apply, the value can be + MAIL_THREAD_REFERENCES, MAIL_THREAD_REFERENCES_NO_SUBJECT, + MAIL_THREAD_ORDEREDSUBJECT or MAIL_THREAD_NONE, + + @param default_from is the default charset to use whenever the + subject is not tagged with a charset. "US-ASCII" can be used + if you don't know what to use. + + @param env_list is the message list (with header fields fetched) + to use to build the message tree. + + @param result * result) will contain the resulting message tree. + + @param if comp_func is NULL, no sorting algorithm is used. + + @return MAIL_NO_ERROR is returned on success, MAIL_ERROR_XXX is returned + on error +*/ + +int mail_build_thread(int type, char * default_from, + struct mailmessage_list * env_list, + struct mailmessage_tree ** result, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **)); + +/* + mail_thread_sort sort the messages in the message tree, using the + given sort function. + + @param tree is the message tree to sort. + + @param comp_func is the sort function to use (this is the same kind of + functions than those used for qsort()). mailthread_tree_timecomp can be + used for default sort. + + @param sort_sub if this value is 0, only the children of the root message + are sorted. +*/ + +int mail_thread_sort(struct mailmessage_tree * tree, + int (* comp_func)(struct mailmessage_tree **, + struct mailmessage_tree **), + int sort_sub); + +/* + mailthread_tree_timecomp is the default sort function. + + The message are compared by date, then by message numbers. + The tree are given in (* ptree1) and (* ptree2). +*/ + +int mailthread_tree_timecomp(struct mailmessage_tree ** ptree1, + struct mailmessage_tree ** ptree2); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/driver/tools/mailthread_types.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/tools/mailthread_types.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,94 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailthread_types.c,v 1.12 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailthread_types.h" + +#include "mail.h" +#include <stdlib.h> + +struct mailmessage_tree * +mailmessage_tree_new(char * node_msgid, time_t node_date, + mailmessage * node_msg) +{ + struct mailmessage_tree * tree; + carray * array; + + array = carray_new(16); + if (array == NULL) + return NULL; + + tree = malloc(sizeof(* tree)); + tree->node_parent = NULL; + tree->node_date = node_date; + tree->node_msgid = node_msgid; + tree->node_msg = node_msg; + tree->node_children = array; + tree->node_base_subject = NULL; + tree->node_is_reply = FALSE; + + return tree; +} + +void mailmessage_tree_free(struct mailmessage_tree * tree) +{ + if (tree->node_base_subject != NULL) + free(tree->node_base_subject); + + if (tree->node_children != NULL) + carray_free(tree->node_children); + if (tree->node_msgid != NULL) + free(tree->node_msgid); + + free(tree); +} + +void mailmessage_tree_free_recursive(struct mailmessage_tree * tree) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(tree->node_children) ; i++) { + struct mailmessage_tree * child; + + child = carray_get(tree->node_children, i); + + mailmessage_tree_free_recursive(child); + } + + mailmessage_tree_free(tree); +} Added: freeswitch/trunk/libs/libetpan/src/driver/tools/mailthread_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/driver/tools/mailthread_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,64 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailthread_types.h,v 1.9 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifndef MAILTHREAD_TYPES_H + +#define MAILTHREAD_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/maildriver_types.h> +#include <libetpan/mailmessage_types.h> + +/* + This is the type of tree construction to apply. +*/ + +enum { + MAIL_THREAD_REFERENCES, /* this is threading using + References fields only) */ + MAIL_THREAD_REFERENCES_NO_SUBJECT, /* this is threading using References + fields, then subject */ + MAIL_THREAD_ORDEREDSUBJECT, /* this is threading using only subject */ + MAIL_THREAD_NONE /* no thread */ +}; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/engine/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/engine/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/engine/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/engine/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,21 @@ +top_builddir = ../.. + +TARGET = libengine +HEADERS = mailengine.h \ + mailprivacy.h \ + mailprivacy_gnupg.h \ + mailprivacy_smime.h \ + mailprivacy_types.h \ + mailprivacy_tools.h + + +SOURCES = mailengine.c \ + mailprivacy.c \ + mailprivacy_gnupg.c \ + mailprivacy_smime.c \ + mailprivacy_tools.c + +INCLUDES = -I$(srcdir)/driver/interface \ + -I$(srcdir)/driver/implementation/imap + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/engine/mailengine.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/engine/mailengine.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1479 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailengine.c,v 1.11 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailengine.h" + +#include "mailfolder.h" +#include "maildriver.h" +#include "imapdriver_cached.h" +#include "mailstorage.h" +#include "imapdriver_cached_message.h" +#include <stdlib.h> +#include "mailprivacy.h" +#ifdef LIBETPAN_REENTRANT +#include <pthread.h> +#endif +#include <string.h> + + +/* ************************************************************* */ +/* Message ref info */ + +struct message_ref_elt { + mailmessage * msg; + int ref_count; + int mime_ref_count; + struct mailfolder * folder; + int lost; +#ifdef LIBETPAN_REENTRANT + pthread_mutex_t lock; +#endif +}; + +static struct message_ref_elt * +message_ref_elt_new(struct mailfolder * folder, mailmessage * msg) +{ + struct message_ref_elt * ref; + int r; + + ref = malloc(sizeof(* ref)); + if (ref == NULL) + goto err; + +#ifdef LIBETPAN_REENTRANT + r = pthread_mutex_init(&ref->lock, NULL); + if (r != 0) + goto free; +#endif + + ref->msg = msg; + ref->ref_count = 0; + ref->mime_ref_count = 0; + ref->folder = folder; + ref->lost = 0; + + return ref; + + free: + free(ref); + err: + return NULL; +} + +static void message_ref_elt_free(struct message_ref_elt * ref_elt) +{ +#ifdef LIBETPAN_REENTRANT + pthread_mutex_destroy(&ref_elt->lock); +#endif + free(ref_elt); +} + +static inline int message_ref(struct message_ref_elt * ref_elt) +{ + int count; + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&ref_elt->lock); +#endif + + ref_elt->ref_count ++; + count = ref_elt->ref_count; + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&ref_elt->lock); +#endif + + return count; +} + +static inline int message_unref(struct message_ref_elt * ref_elt) +{ + int count; + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&ref_elt->lock); +#endif + + ref_elt->ref_count --; + count = ref_elt->ref_count; + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&ref_elt->lock); +#endif + + return count; +} + + +static inline int message_mime_ref(struct mailprivacy * privacy, + struct message_ref_elt * ref_elt) +{ + int r; + int count; + + if (ref_elt->mime_ref_count == 0) { + struct mailmime * mime; + + r = mailprivacy_msg_get_bodystructure(privacy, ref_elt->msg, &mime); + if (r != MAIL_NO_ERROR) + return -r; + } + + message_ref(ref_elt); + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&ref_elt->lock); +#endif + ref_elt->mime_ref_count ++; + count = ref_elt->mime_ref_count; +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&ref_elt->lock); +#endif + + return count; +} + +static inline int message_mime_unref(struct mailprivacy * privacy, + struct message_ref_elt * ref_elt) +{ + int count; + + message_unref(ref_elt); + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&ref_elt->lock); +#endif + ref_elt->mime_ref_count --; + + if (ref_elt->mime_ref_count == 0) + mailprivacy_msg_flush(privacy, ref_elt->msg); + + count = ref_elt->mime_ref_count; + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&ref_elt->lock); +#endif + + return count; +} + + +/* ************************************************************* */ +/* Folder ref info */ + +struct folder_ref_info { + struct mailfolder * folder; + + /* msg => msg_ref_info */ + chash * msg_hash; + + /* uid => msg */ + chash * uid_hash; + + int lost_session; +}; + +static struct folder_ref_info * +folder_ref_info_new(struct mailfolder * folder + /*, struct message_folder_finder * msg_folder_finder */) +{ + struct folder_ref_info * ref_info; + + ref_info = malloc(sizeof(* ref_info)); + if (ref_info == NULL) + goto err; + + ref_info->folder = folder; + + ref_info->msg_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (ref_info->msg_hash == NULL) + goto free; + + ref_info->uid_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE); + if (ref_info->uid_hash == NULL) + goto free_msg_hash; + + ref_info->lost_session = 1; + + return ref_info; + + free_msg_hash: + chash_free(ref_info->msg_hash); + free: + free(ref_info); + err: + return NULL; +} + +static void folder_ref_info_free(struct folder_ref_info * ref_info) +{ + chash_free(ref_info->uid_hash); + chash_free(ref_info->msg_hash); + free(ref_info); +} + +static struct message_ref_elt * +folder_info_get_msg_ref(struct folder_ref_info * ref_info, mailmessage * msg) +{ + chashdatum key; + chashdatum data; + struct message_ref_elt * ref_elt; + int r; + + key.data = &msg; + key.len = sizeof(msg); + r = chash_get(ref_info->msg_hash, &key, &data); + if (r < 0) + return NULL; + + ref_elt = data.data; + + return ref_elt; +} + +static mailmessage * +folder_info_get_msg_by_uid(struct folder_ref_info * ref_info, + char * uid) +{ + chashdatum key; + chashdatum data; + mailmessage * msg; + int r; + + key.data = uid; + key.len = strlen(uid); + r = chash_get(ref_info->uid_hash, &key, &data); + if (r < 0) + return NULL; + + msg = data.data; + + return msg; +} + +static int folder_message_ref(struct folder_ref_info * ref_info, + mailmessage * msg) +{ + struct message_ref_elt * msg_ref; + + msg_ref = folder_info_get_msg_ref(ref_info, msg); + return message_ref(msg_ref); +} + +static void folder_message_remove(struct folder_ref_info * ref_info, + mailmessage * msg); + +#ifdef DEBUG_ENGINE +#include "etpan-app.h" + +void * engine_app = NULL; +#endif + +static int folder_message_unref(struct folder_ref_info * ref_info, + mailmessage * msg) +{ + struct message_ref_elt * msg_ref; + int count; + + msg_ref = folder_info_get_msg_ref(ref_info, msg); + + if (msg_ref->ref_count == 0) { +#ifdef ETPAN_APP_DEBUG + ETPAN_APP_DEBUG((engine_app, "** BUG detected negative ref count !")); +#endif + } + + count = message_unref(msg_ref); + if (count == 0) { + folder_message_remove(ref_info, msg); + mailmessage_free(msg); + } + + return count; +} + +static int folder_message_mime_ref(struct mailprivacy * privacy, + struct folder_ref_info * ref_info, + mailmessage * msg) +{ + struct message_ref_elt * msg_ref; + + msg_ref = folder_info_get_msg_ref(ref_info, msg); + + return message_mime_ref(privacy, msg_ref); +} + +static int folder_message_mime_unref(struct mailprivacy * privacy, + struct folder_ref_info * ref_info, + mailmessage * msg) +{ + struct message_ref_elt * msg_ref; + + msg_ref = folder_info_get_msg_ref(ref_info, msg); + return message_mime_unref(privacy, msg_ref); +} + +static int folder_message_add(struct folder_ref_info * ref_info, + mailmessage * msg) +{ + chashdatum key; + chashdatum data; + struct message_ref_elt * msg_ref; + int r; + + msg_ref = message_ref_elt_new(ref_info->folder, msg); + if (msg_ref == NULL) + goto err; + + key.data = &msg; + key.len = sizeof(msg); + data.data = msg_ref; + data.len = 0; + + r = chash_set(ref_info->msg_hash, &key, &data, NULL); + if (r < 0) + goto free_msg_ref; + + if (msg->msg_uid != NULL) { + key.data = msg->msg_uid; + key.len = strlen(msg->msg_uid); + data.data = msg; + data.len = 0; + + r = chash_set(ref_info->uid_hash, &key, &data, NULL); + if (r < 0) + goto remove_msg_ref; + } + + return MAIL_NO_ERROR; + + remove_msg_ref: + key.data = &msg; + key.len = sizeof(msg); + chash_delete(ref_info->msg_hash, &key, NULL); + free_msg_ref: + message_ref_elt_free(msg_ref); + err: + return MAIL_ERROR_MEMORY; +} + + +static void folder_message_remove(struct folder_ref_info * ref_info, + mailmessage * msg) +{ + chashdatum key; + struct message_ref_elt * msg_ref; + + if (msg->msg_uid != NULL) { + key.data = msg->msg_uid; + key.len = strlen(msg->msg_uid); + + chash_delete(ref_info->uid_hash, &key, NULL); + } + + msg_ref = folder_info_get_msg_ref(ref_info, msg); + message_ref_elt_free(msg_ref); + + key.data = &msg; + key.len = sizeof(msg); + + chash_delete(ref_info->msg_hash, &key, NULL); +} + + +static int folder_update_msg_list(struct folder_ref_info * ref_info, + struct mailmessage_list ** p_new_msg_list, + struct mailmessage_list ** p_lost_msg_list) +{ + int r; + int res; + struct mailmessage_list * new_env_list; + unsigned int i; + carray * lost_msg_tab; + struct mailmessage_list * lost_msg_list; + unsigned int free_start_index; + chashiter * iter; + unsigned int lost_count; + + r = mailfolder_get_messages_list(ref_info->folder, &new_env_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + for(iter = chash_begin(ref_info->msg_hash) ; iter != NULL ; + iter = chash_next(ref_info->msg_hash, iter)) { + struct message_ref_elt * msg_ref; + chashdatum data; + + chash_value(iter, &data); + msg_ref = data.data; + msg_ref->lost = 1; + } + + lost_count = chash_count(ref_info->msg_hash); + + for(i = 0 ; i < carray_count(new_env_list->msg_tab) ; i ++) { + mailmessage * msg; + mailmessage * old_msg; + + msg = carray_get(new_env_list->msg_tab, i); + + if (msg->msg_uid == NULL) + continue; + + old_msg = folder_info_get_msg_by_uid(ref_info, msg->msg_uid); + if (old_msg != NULL) { + struct message_ref_elt * msg_ref; + + /* replace old message */ + old_msg->msg_index = msg->msg_index; + carray_set(new_env_list->msg_tab, i, old_msg); + mailmessage_free(msg); + + msg_ref = folder_info_get_msg_ref(ref_info, old_msg); + msg_ref->lost = 0; + lost_count --; + } + else { + /* set new message */ + r = folder_message_add(ref_info, msg); + if (r != MAIL_NO_ERROR) { + free_start_index = i; + res = r; + goto free_remaining; + } + } + } + + /* build the table of lost messages */ + lost_msg_tab = carray_new(lost_count); + if (lost_msg_tab == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_env_list; + } + + carray_set_size(lost_msg_tab, lost_count); + + i = 0; + for(iter = chash_begin(ref_info->msg_hash) ; iter != NULL ; + iter = chash_next(ref_info->msg_hash, iter)) { + struct message_ref_elt * msg_ref; + chashdatum key; + chashdatum value; + mailmessage * msg; + + chash_key(iter, &key); + memcpy(&msg, key.data, sizeof(msg)); + + chash_value(iter, &value); + msg_ref = value.data; + if (msg_ref->lost) { + carray_set(lost_msg_tab, i, msg); + i ++; + } + } + + lost_msg_list = mailmessage_list_new(lost_msg_tab); + if (lost_msg_list == NULL) { + res = MAIL_ERROR_MEMORY; + goto free_lost_msg_tab; + } + + /* reference messages */ + for(i = 0 ; i < carray_count(new_env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(new_env_list->msg_tab, i); + folder_message_ref(ref_info, msg); + } + + * p_new_msg_list = new_env_list; + * p_lost_msg_list = lost_msg_list; + + return MAIL_NO_ERROR; + + free_lost_msg_tab: + carray_free(lost_msg_tab); + free_env_list: + for(i = 0 ; i < carray_count(new_env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct message_ref_elt * msg_ref; + + msg = carray_get(new_env_list->msg_tab, i); + msg_ref = folder_info_get_msg_ref(ref_info, msg); + if (msg_ref != NULL) { + if (msg_ref->ref_count == 0) + folder_message_remove(ref_info, msg); + } + } + carray_set_size(new_env_list->msg_tab, 0); + mailmessage_list_free(new_env_list); + goto err; + free_remaining: + for(i = 0 ; i < carray_count(new_env_list->msg_tab) ; i ++) { + mailmessage * msg; + struct message_ref_elt * msg_ref; + + msg = carray_get(new_env_list->msg_tab, i); + msg_ref = folder_info_get_msg_ref(ref_info, msg); + if (msg_ref != NULL) { + if (msg_ref->ref_count == 0) + folder_message_remove(ref_info, msg); + } + } + for(i = free_start_index ; i < carray_count(new_env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(new_env_list->msg_tab, i); + mailmessage_free(msg); + } + carray_set_size(new_env_list->msg_tab, 0); + mailmessage_list_free(new_env_list); + err: + return res; +} + +/* + folder_fetch_env_list() +*/ + +static int folder_fetch_env_list(struct folder_ref_info * ref_info, + struct mailmessage_list * msg_list) +{ + return mailfolder_get_envelopes_list(ref_info->folder, msg_list); +} + +static void folder_free_msg_list(struct folder_ref_info * ref_info, + struct mailmessage_list * env_list) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + int count; + + msg = carray_get(env_list->msg_tab, i); + + count = folder_message_unref(ref_info, msg); + } + carray_set_size(env_list->msg_tab, 0); + mailmessage_list_free(env_list); +} + + +/* ************************************************************* */ +/* Storage ref info */ + +struct storage_ref_info { + struct mailstorage * storage; + + /* folder => folder_ref_info */ + chash * folder_ref_info; +}; + +static struct storage_ref_info * +storage_ref_info_new(struct mailstorage * storage + /*, struct message_folder_finder * msg_folder_finder */) +{ + struct storage_ref_info * ref_info; + + ref_info = malloc(sizeof(* ref_info)); + if (ref_info == NULL) + goto err; + + ref_info->storage = storage; + + ref_info->folder_ref_info = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (ref_info->folder_ref_info == NULL) + goto free; + + return ref_info; + + free: + free(ref_info); + err: + return NULL; +} + +static void storage_ref_info_free(struct storage_ref_info * ref_info) +{ + chash_free(ref_info->folder_ref_info); + free(ref_info); +} + + +static struct folder_ref_info * +storage_get_folder_ref(struct storage_ref_info * ref_info, + struct mailfolder * folder) +{ + struct folder_ref_info * folder_ref; + chashdatum key; + chashdatum value; + int r; + + key.data = &folder; + key.len = sizeof(folder); + r = chash_get(ref_info->folder_ref_info, &key, &value); + if (r < 0) + return NULL; + + folder_ref = value.data; + + return folder_ref; +} + +static struct folder_ref_info * +storage_folder_add_ref(struct storage_ref_info * ref_info, + struct mailfolder * folder) +{ + struct folder_ref_info * folder_ref; + chashdatum key; + chashdatum value; + int r; + + folder_ref = folder_ref_info_new(folder /*, ref_info->msg_folder_finder */); + if (folder_ref == NULL) + goto err; + + key.data = &folder; + key.len = sizeof(folder); + value.data = folder_ref; + value.len = 0; + r = chash_set(ref_info->folder_ref_info, &key, &value, NULL); + if (r < 0) + goto free; + + return folder_ref; + + free: + folder_ref_info_free(folder_ref); + err: + return NULL; +} + + +static void storage_folder_remove_ref(struct storage_ref_info * ref_info, + struct mailfolder * folder) +{ + struct folder_ref_info * folder_ref; + chashdatum key; + chashdatum value; + int r; + + key.data = &folder; + key.len = sizeof(folder); + r = chash_get(ref_info->folder_ref_info, &key, &value); + if (r < 0) + return; + + folder_ref = value.data; + + if (folder_ref == NULL) + return; + + folder_ref_info_free(folder_ref); + + chash_delete(ref_info->folder_ref_info, &key, &value); +} + +static int storage_folder_get_msg_list(struct storage_ref_info * ref_info, + struct mailfolder * folder, + struct mailmessage_list ** p_new_msg_list, + struct mailmessage_list ** p_lost_msg_list) +{ + struct folder_ref_info * folder_ref_info; + + folder_ref_info = storage_get_folder_ref(ref_info, folder); + if (folder_ref_info == NULL) + return MAIL_ERROR_INVAL; + + return folder_update_msg_list(folder_ref_info, + p_new_msg_list, p_lost_msg_list); +} + +static int storage_folder_fetch_env_list(struct storage_ref_info * ref_info, + struct mailfolder * folder, + struct mailmessage_list * msg_list) +{ + struct folder_ref_info * folder_ref_info; + + folder_ref_info = storage_get_folder_ref(ref_info, folder); + if (folder_ref_info == NULL) + return MAIL_ERROR_INVAL; + + return folder_fetch_env_list(folder_ref_info, msg_list); +} + +static void +storage_folder_free_msg_list(struct storage_ref_info * ref_info, + struct mailfolder * folder, + struct mailmessage_list * env_list) +{ + struct folder_ref_info * folder_ref_info; + + folder_ref_info = storage_get_folder_ref(ref_info, folder); + + folder_free_msg_list(folder_ref_info, env_list); +} + + +/* connection and disconnection */ + +static void +folder_restore_session(struct folder_ref_info * ref_info) +{ + chashiter * iter; + mailsession * session; + + session = ref_info->folder->fld_session; + + for(iter = chash_begin(ref_info->msg_hash) ; iter != NULL ; + iter = chash_next(ref_info->msg_hash, iter)) { + chashdatum key; + mailmessage * msg; + + chash_key(iter, &key); + memcpy(&msg, key.data, sizeof(msg)); + msg->msg_session = session; + + if (msg->msg_driver == imap_cached_message_driver) { + struct imap_cached_session_state_data * imap_cached_data; + mailmessage * ancestor_msg; + + imap_cached_data = ref_info->folder->fld_session->sess_data; + ancestor_msg = msg->msg_data; + ancestor_msg->msg_session = imap_cached_data->imap_ancestor; + } + } +} + +static void +storage_restore_message_session(struct storage_ref_info * ref_info) +{ + chashiter * iter; + + for(iter = chash_begin(ref_info->folder_ref_info) ; iter != NULL ; + iter = chash_next(ref_info->folder_ref_info, iter)) { + chashdatum data; + struct folder_ref_info * folder_ref_info; + + chash_value(iter, &data); + folder_ref_info = data.data; + if (folder_ref_info->lost_session) { + if (folder_ref_info->folder->fld_session != NULL) { + /* restore folder session */ + folder_restore_session(folder_ref_info); + + folder_ref_info->lost_session = 0; + } + } + } +} + + +static int do_storage_connect(struct storage_ref_info * ref_info) +{ + int r; + + r = mailstorage_connect(ref_info->storage); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +static void do_storage_disconnect(struct storage_ref_info * ref_info) +{ + clistiter * cur; + + /* storage is disconnected, session is lost */ + for(cur = clist_begin(ref_info->storage->sto_shared_folders) ; cur != NULL ; + cur = clist_next(cur)) { + struct folder_ref_info * folder_ref_info; + struct mailfolder * folder; + + folder = clist_content(cur); + /* folder is disconnected (in storage), session is lost */ + + folder_ref_info = storage_get_folder_ref(ref_info, folder); + folder_ref_info->lost_session = 1; + } + + /* storage is disconnected */ + mailstorage_disconnect(ref_info->storage); +} + + + +static int folder_connect(struct storage_ref_info * ref_info, + struct mailfolder * folder) +{ + int r; + struct folder_ref_info * folder_ref_info; + + r = do_storage_connect(ref_info); + if (r != MAIL_NO_ERROR) + return r; + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) + return r; + + folder_ref_info = storage_get_folder_ref(ref_info, folder); + + return MAIL_NO_ERROR; +} + + +static void folder_disconnect(struct storage_ref_info * ref_info, + struct mailfolder * folder) +{ + struct folder_ref_info * folder_ref_info; + + folder_ref_info = storage_get_folder_ref(ref_info, folder); + + /* folder is disconnected, session is lost */ + folder_ref_info->lost_session = 1; + mailfolder_disconnect(folder); + + if (folder->fld_shared_session) + do_storage_disconnect(ref_info); +} + + +static int storage_folder_connect(struct storage_ref_info * ref_info, + struct mailfolder * folder) +{ + int r; + int res; + struct folder_ref_info * folder_ref_info; + + folder_ref_info = storage_get_folder_ref(ref_info, folder); + if (folder_ref_info == NULL) { + folder_ref_info = storage_folder_add_ref(ref_info, folder); + if (folder_ref_info == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + } + + /* connect folder */ + + r = folder_connect(ref_info, folder); + if (r == MAIL_ERROR_STREAM) { + /* properly handles disconnection */ + + /* reconnect */ + folder_disconnect(ref_info, folder); + r = folder_connect(ref_info, folder); + } + + if (r != MAIL_NO_ERROR) { + res = r; + goto remove_ref; + } + + /* test folder connection */ + r = mailfolder_noop(folder); + if (r == MAIL_ERROR_STREAM) { + /* reconnect */ + folder_disconnect(ref_info, folder); + r = folder_connect(ref_info, folder); + } + + if ((r != MAIL_ERROR_NOT_IMPLEMENTED) && (r != MAIL_NO_ERROR)) { + res = r; + goto disconnect; + } + + storage_restore_message_session(ref_info); + + return MAIL_NO_ERROR; + + disconnect: + folder_disconnect(ref_info, folder); + remove_ref: + storage_folder_remove_ref(ref_info, folder); + err: + return res; +} + +static void storage_folder_disconnect(struct storage_ref_info * ref_info, + struct mailfolder * folder) +{ + mailfolder_disconnect(folder); + storage_folder_remove_ref(ref_info, folder); +} + +static int storage_connect(struct storage_ref_info * ref_info) +{ + int r; + int res; + + /* connect storage */ + + /* properly handles disconnection */ + r = do_storage_connect(ref_info); + if (r == MAIL_ERROR_STREAM) { + /* reconnect storage */ + do_storage_disconnect(ref_info); + r = do_storage_connect(ref_info); + } + + if (r != MAIL_NO_ERROR) { + res = r; + goto disconnect; + } + + /* test storage connection */ + + r = mailsession_noop(ref_info->storage->sto_session); + if ((r != MAIL_ERROR_NOT_IMPLEMENTED) && (r != MAIL_NO_ERROR)) { + /* properly handles disconnection */ + + /* reconnect storage */ + do_storage_disconnect(ref_info); + r = do_storage_connect(ref_info); + } + + if (r != MAIL_NO_ERROR) { + res = r; + goto disconnect; + } + + storage_restore_message_session(ref_info); + + return MAIL_NO_ERROR; + + disconnect: + do_storage_disconnect(ref_info); + return res; +} + + +static void storage_disconnect(struct storage_ref_info * ref_info) +{ + chashiter * iter; + + /* disconnect folders */ + while ((iter = chash_begin(ref_info->folder_ref_info)) != NULL) { + chashdatum key; + struct mailfolder * folder; + + chash_key(iter, &key); + memcpy(&folder, key.data, sizeof(folder)); + + storage_folder_disconnect(ref_info, folder); + } + + /* disconnect storage */ + do_storage_disconnect(ref_info); +} + + +/* ************************************************************* */ +/* interface for mailengine */ + +struct mailengine { + struct mailprivacy * privacy; + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_t storage_hash_lock; +#endif + /* storage => storage_ref_info */ + chash * storage_hash; +}; + +static struct storage_ref_info * +get_storage_ref_info(struct mailengine * engine, + struct mailstorage * storage) +{ + chashdatum key; + chashdatum data; + int r; + struct storage_ref_info * ref_info; + + key.data = &storage; + key.len = sizeof(storage); +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&engine->storage_hash_lock); +#endif + r = chash_get(engine->storage_hash, &key, &data); +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&engine->storage_hash_lock); +#endif + if (r < 0) + return NULL; + + ref_info = data.data; + + return ref_info; +} + +static struct storage_ref_info * +add_storage_ref_info(struct mailengine * engine, + struct mailstorage * storage) +{ + chashdatum key; + chashdatum data; + int r; + struct storage_ref_info * ref_info; + + ref_info = storage_ref_info_new(storage + /* , &engine->msg_folder_finder */); + if (ref_info == NULL) + goto err; + + key.data = &storage; + key.len = sizeof(storage); + data.data = ref_info; + data.len = 0; + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&engine->storage_hash_lock); +#endif + r = chash_set(engine->storage_hash, &key, &data, NULL); +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&engine->storage_hash_lock); +#endif + if (r < 0) + goto free; + + ref_info = data.data; + + return ref_info; + + free: + storage_ref_info_free(ref_info); + err: + return NULL; +} + +static void +remove_storage_ref_info(struct mailengine * engine, + struct mailstorage * storage) +{ + chashdatum key; + chashdatum data; + struct storage_ref_info * ref_info; + + key.data = &storage; + key.len = sizeof(storage); + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&engine->storage_hash_lock); +#endif + + chash_get(engine->storage_hash, &key, &data); + ref_info = data.data; + + if (ref_info != NULL) { + storage_ref_info_free(ref_info); + + chash_delete(engine->storage_hash, &key, NULL); + } + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&engine->storage_hash_lock); +#endif +} + +struct mailengine * +libetpan_engine_new(struct mailprivacy * privacy) +{ + struct mailengine * engine; + int r; + + engine = malloc(sizeof(* engine)); + if (engine == NULL) + goto err; + + engine->privacy = privacy; + +#ifdef LIBETPAN_REENTRANT + r = pthread_mutex_init(&engine->storage_hash_lock, NULL); + if (r != 0) + goto free; +#endif + + engine->storage_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (engine->storage_hash == NULL) + goto destroy_mutex; + + return engine; + + destroy_mutex: +#ifdef LIBETPAN_REENTRANT + pthread_mutex_destroy(&engine->storage_hash_lock); +#endif + free: + free(engine); + err: + return NULL; +} + +void libetpan_engine_free(struct mailengine * engine) +{ + chash_free(engine->storage_hash); +#ifdef LIBETPAN_REENTRANT + pthread_mutex_destroy(&engine->storage_hash_lock); +#endif + free(engine); +} + +static struct folder_ref_info * +message_get_folder_ref(struct mailengine * engine, + mailmessage * msg) +{ + struct mailfolder * folder; + struct mailstorage * storage; + struct storage_ref_info * storage_ref_info; + struct folder_ref_info * folder_ref_info; + + folder = msg->msg_folder; + if (folder == NULL) + storage = NULL; + else + storage = folder->fld_storage; + + storage_ref_info = get_storage_ref_info(engine, storage); + + folder_ref_info = storage_get_folder_ref(storage_ref_info, folder); + + return folder_ref_info; +} + +int libetpan_message_ref(struct mailengine * engine, + mailmessage * msg) +{ + struct folder_ref_info * ref_info; + + ref_info = message_get_folder_ref(engine, msg); + + return folder_message_ref(ref_info, msg); +} + +int libetpan_message_unref(struct mailengine * engine, + mailmessage * msg) +{ + struct folder_ref_info * ref_info; + + ref_info = message_get_folder_ref(engine, msg); + + return folder_message_unref(ref_info, msg); +} + + +int libetpan_message_mime_ref(struct mailengine * engine, + mailmessage * msg) +{ + struct folder_ref_info * ref_info; + + ref_info = message_get_folder_ref(engine, msg); + + return folder_message_mime_ref(engine->privacy, ref_info, msg); +} + +int libetpan_message_mime_unref(struct mailengine * engine, + mailmessage * msg) +{ + struct folder_ref_info * ref_info; + + ref_info = message_get_folder_ref(engine, msg); + + return folder_message_mime_unref(engine->privacy, ref_info, msg); +} + +int libetpan_folder_get_msg_list(struct mailengine * engine, + struct mailfolder * folder, + struct mailmessage_list ** p_new_msg_list, + struct mailmessage_list ** p_lost_msg_list) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, folder->fld_storage); + + return storage_folder_get_msg_list(ref_info, folder, + p_new_msg_list, p_lost_msg_list); +} + +int libetpan_folder_fetch_env_list(struct mailengine * engine, + struct mailfolder * folder, + struct mailmessage_list * msg_list) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, folder->fld_storage); + + return storage_folder_fetch_env_list(ref_info, folder, msg_list); +} + +void libetpan_folder_free_msg_list(struct mailengine * engine, + struct mailfolder * folder, + struct mailmessage_list * env_list) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, folder->fld_storage); + + storage_folder_free_msg_list(ref_info, folder, env_list); +} + + +int libetpan_storage_add(struct mailengine * engine, + struct mailstorage * storage) +{ + struct storage_ref_info * storage_ref_info; + struct folder_ref_info * folder_ref_info; + + storage_ref_info = add_storage_ref_info(engine, storage); + if (storage_ref_info == NULL) + goto err; + + if (storage == NULL) { + folder_ref_info = storage_folder_add_ref(storage_ref_info, NULL); + if (folder_ref_info == NULL) + goto remove_storage_ref_info; + } + + return MAIL_NO_ERROR; + + remove_storage_ref_info: + remove_storage_ref_info(engine, storage); + err: + return MAIL_ERROR_MEMORY; +} + +void libetpan_storage_remove(struct mailengine * engine, + struct mailstorage * storage) +{ + struct storage_ref_info * storage_ref_info; + + storage_ref_info = get_storage_ref_info(engine, storage); + if (storage == NULL) { + storage_folder_remove_ref(storage_ref_info, NULL); + } + + remove_storage_ref_info(engine, storage); +} + +int libetpan_storage_connect(struct mailengine * engine, + struct mailstorage * storage) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, storage); + + return storage_connect(ref_info); +} + + +void libetpan_storage_disconnect(struct mailengine * engine, + struct mailstorage * storage) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, storage); + + storage_disconnect(ref_info); +} + +int libetpan_storage_used(struct mailengine * engine, + struct mailstorage * storage) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, storage); + + return (chash_count(ref_info->folder_ref_info) != 0); +} + + +int libetpan_folder_connect(struct mailengine * engine, + struct mailfolder * folder) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, folder->fld_storage); + + return storage_folder_connect(ref_info, folder); +} + + +void libetpan_folder_disconnect(struct mailengine * engine, + struct mailfolder * folder) +{ + struct storage_ref_info * ref_info; + + ref_info = get_storage_ref_info(engine, folder->fld_storage); + + storage_folder_disconnect(ref_info, folder); +} + + +struct mailfolder * +libetpan_message_get_folder(struct mailengine * engine, + mailmessage * msg) +{ + return msg->msg_folder; +} + + +struct mailstorage * +libetpan_message_get_storage(struct mailengine * engine, + mailmessage * msg) +{ + struct mailfolder * folder; + + folder = libetpan_message_get_folder(engine, msg); + + if (folder == NULL) + return NULL; + else + return folder->fld_storage; +} + + +int libetpan_message_register(struct mailengine * engine, + struct mailfolder * folder, + mailmessage * msg) +{ + struct storage_ref_info * storage_ref_info; + int r; + int res; + struct folder_ref_info * folder_ref_info; + struct mailstorage * storage; + + if (folder != NULL) + storage = folder->fld_storage; + else + storage = NULL; + + storage_ref_info = get_storage_ref_info(engine, storage); + + folder_ref_info = storage_get_folder_ref(storage_ref_info, folder); + + r = folder_message_add(folder_ref_info, msg); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +struct mailprivacy * +libetpan_engine_get_privacy(struct mailengine * engine) +{ + return engine->privacy; +} + + +static void folder_debug(struct folder_ref_info * folder_ref_info, FILE * f) +{ + fprintf(f, "folder debug -- begin\n"); + if (folder_ref_info->folder == NULL) { + fprintf(f, "NULL folder\n"); + } + else { + if (folder_ref_info->folder->fld_virtual_name != NULL) + fprintf(f, "folder %s\n", folder_ref_info->folder->fld_virtual_name); + else + fprintf(f, "folder [no name]\n"); + } + + fprintf(f, "message count: %i\n", chash_count(folder_ref_info->msg_hash)); + fprintf(f, "UID count: %i\n", chash_count(folder_ref_info->uid_hash)); + fprintf(f, "folder debug -- end\n"); +} + +static void storage_debug(struct storage_ref_info * storage_ref_info, FILE * f) +{ + chashiter * iter; + + fprintf(f, "storage debug -- begin\n"); + if (storage_ref_info->storage == NULL) { + fprintf(f, "NULL storage\n"); + } + else { + if (storage_ref_info->storage->sto_id != NULL) + fprintf(f, "storage %s\n", storage_ref_info->storage->sto_id); + else + fprintf(f, "storage [no name]\n"); + } + fprintf(f, "folder count: %i\n", + chash_count(storage_ref_info->folder_ref_info)); + + for(iter = chash_begin(storage_ref_info->folder_ref_info) ; iter != NULL ; + iter = chash_next(storage_ref_info->folder_ref_info, iter)) { + chashdatum data; + struct folder_ref_info * folder_ref_info; + + chash_value(iter, &data); + folder_ref_info = data.data; + + folder_debug(folder_ref_info, f); + } + fprintf(f, "storage debug -- end\n"); +} + +void libetpan_engine_debug(struct mailengine * engine, FILE * f) +{ + chashiter * iter; + + fprintf(f, "mail engine debug -- begin\n"); + + for(iter = chash_begin(engine->storage_hash) ; iter != NULL ; + iter = chash_next(engine->storage_hash, iter)) { + chashdatum data; + struct storage_ref_info * storage_ref_info; + + chash_value(iter, &data); + storage_ref_info = data.data; + + storage_debug(storage_ref_info, f); + } + + fprintf(f, "mail engine debug -- end\n"); +} + Added: freeswitch/trunk/libs/libetpan/src/engine/mailengine.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/engine/mailengine.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,190 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailengine.h,v 1.3 2004/11/21 21:53:35 hoa Exp $ + */ + +#ifndef MAILENGINE_H + +#define MAILENGINE_H + +#include <libetpan/mailmessage.h> +#include <libetpan/mailfolder.h> +#include <libetpan/mailprivacy_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + to run things in thread, you must protect the storage again concurrency. +*/ + + +/* + storage data +*/ + +struct mailengine * +libetpan_engine_new(struct mailprivacy * privacy); + +void libetpan_engine_free(struct mailengine * engine); + + +struct mailprivacy * +libetpan_engine_get_privacy(struct mailengine * engine); + + +/* + message ref and unref +*/ + +/* + these function can only take messages returned by get_msg_list() + as arguments. + + these functions cannot fail. +*/ + +int libetpan_message_ref(struct mailengine * engine, + mailmessage * msg); + +int libetpan_message_unref(struct mailengine * engine, + mailmessage * msg); + + +/* + when you want to access the MIME structure of the message + with msg->mime, you have to call libetpan_message_mime_ref() + and libetpan_message_mime_unref() when you have finished. + + if libetpan_mime_ref() returns a value <= 0, it means this failed. + the value is -MAIL_ERROR_XXX +*/ + +int libetpan_message_mime_ref(struct mailengine * engine, + mailmessage * msg); + +int libetpan_message_mime_unref(struct mailengine * engine, + mailmessage * msg); + +/* + message list +*/ + +/* + libetpan_folder_get_msg_list() + + This function returns two list. + - List of lost message (the messages that were previously returned + but that does no more exist) (p_lost_msg_list) + - List of valid messages (p_new_msg_list). + + These two list can only be freed by libetpan_folder_free_msg_list() +*/ + +int libetpan_folder_get_msg_list(struct mailengine * engine, + struct mailfolder * folder, + struct mailmessage_list ** p_new_msg_list, + struct mailmessage_list ** p_lost_msg_list); + +int libetpan_folder_fetch_env_list(struct mailengine * engine, + struct mailfolder * folder, + struct mailmessage_list * msg_list); + +void libetpan_folder_free_msg_list(struct mailengine * engine, + struct mailfolder * folder, + struct mailmessage_list * env_list); + + +/* + connect and disconnect storage +*/ + +int libetpan_storage_add(struct mailengine * engine, + struct mailstorage * storage); + +void libetpan_storage_remove(struct mailengine * engine, + struct mailstorage * storage); + +int libetpan_storage_connect(struct mailengine * engine, + struct mailstorage * storage); + +void libetpan_storage_disconnect(struct mailengine * engine, + struct mailstorage * storage); + +int libetpan_storage_used(struct mailengine * engine, + struct mailstorage * storage); + + +/* + libetpan_folder_connect() + libetpan_folder_disconnect() + + You can disconnect the folder only when you have freed all the message + you were given. +*/ + +int libetpan_folder_connect(struct mailengine * engine, + struct mailfolder * folder); + +void libetpan_folder_disconnect(struct mailengine * engine, + struct mailfolder * folder); + + +struct mailfolder * +libetpan_message_get_folder(struct mailengine * engine, + mailmessage * msg); + +struct mailstorage * +libetpan_message_get_storage(struct mailengine * engine, + mailmessage * msg); + + +/* + register a message +*/ + +int libetpan_message_register(struct mailengine * engine, + struct mailfolder * folder, + mailmessage * msg); + + +void libetpan_engine_debug(struct mailengine * engine, FILE * f); + +extern void * engine_app; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/engine/mailprivacy.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/engine/mailprivacy.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,956 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy.c,v 1.7 2006/05/22 13:39:40 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailprivacy.h" + +#include <libetpan/libetpan.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> +#include <stdlib.h> +#include <string.h> +#include "mailprivacy_tools.h" + +carray * mailprivacy_get_protocols(struct mailprivacy * privacy) +{ + return privacy->protocols; +} + +static int recursive_check_privacy(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime); + +static int check_tmp_dir(char * tmp_dir) +{ + struct stat stat_info; + int r; + + r = stat(tmp_dir, &stat_info); + if (r < 0) + return MAIL_ERROR_FILE; + + /* check if the directory belongs to the user */ + if (stat_info.st_uid != getuid()) + return MAIL_ERROR_INVAL; + + if ((stat_info.st_mode & 00777) != 0700) { + r = chmod(tmp_dir, 0700); + if (r < 0) + return MAIL_ERROR_FILE; + } + + return MAIL_NO_ERROR; +} + +struct mailprivacy * mailprivacy_new(char * tmp_dir, int make_alternative) +{ + struct mailprivacy * privacy; + + privacy = malloc(sizeof(* privacy)); + if (privacy == NULL) + goto err; + + privacy->tmp_dir = strdup(tmp_dir); + if (privacy->tmp_dir == NULL) + goto free; + + privacy->msg_ref = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (privacy->msg_ref == NULL) + goto free_tmp_dir; + + privacy->mmapstr = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (privacy->mmapstr == NULL) + goto free_msg_ref; + + privacy->mime_ref = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (privacy->mime_ref == NULL) + goto free_mmapstr; + + privacy->protocols = carray_new(16); + if (privacy->protocols == NULL) + goto free_mime_ref; + + privacy->make_alternative = make_alternative; + + return privacy; + + free_mime_ref: + chash_free(privacy->mime_ref); + free_mmapstr: + chash_free(privacy->mmapstr); + free_msg_ref: + chash_free(privacy->msg_ref); + free_tmp_dir: + free(privacy->tmp_dir); + free: + free(privacy); + err: + return NULL; +} + +void mailprivacy_free(struct mailprivacy * privacy) +{ + carray_free(privacy->protocols); + chash_free(privacy->mime_ref); + chash_free(privacy->mmapstr); + chash_free(privacy->msg_ref); + free(privacy->tmp_dir); + free(privacy); +} + +static int msg_is_modified(struct mailprivacy * privacy, + mailmessage * msg) +{ + chashdatum key; + chashdatum data; + int r; + + if (privacy == NULL) + return 0; + + key.data = &msg; + key.len = sizeof(msg); + + r = chash_get(privacy->msg_ref, &key, &data); + if (r < 0) + return 0; + else + return 1; +} + +static int register_msg(struct mailprivacy * privacy, + mailmessage * msg) +{ + chashdatum key; + chashdatum data; + int r; + + if (privacy == NULL) + return MAIL_NO_ERROR; + + key.data = &msg; + key.len = sizeof(msg); + data.data = msg; + data.len = 0; + + r = chash_set(privacy->msg_ref, &key, &data, NULL); + if (r < 0) + return MAIL_ERROR_MEMORY; + else + return MAIL_NO_ERROR; +} + +static void unregister_message(struct mailprivacy * privacy, + mailmessage * msg) +{ + chashdatum key; + + key.data = &msg; + key.len = sizeof(msg); + + chash_delete(privacy->msg_ref, &key, NULL); +} + +static int result_is_mmapstr(struct mailprivacy * privacy, char * str) +{ + chashdatum key; + chashdatum data; + int r; + + key.data = &str; + key.len = sizeof(str); + + r = chash_get(privacy->mmapstr, &key, &data); + if (r < 0) + return 0; + else + return 1; +} + +static int register_result_mmapstr(struct mailprivacy * privacy, + char * content) +{ + chashdatum key; + chashdatum data; + int r; + + key.data = &content; + key.len = sizeof(content); + data.data = content; + data.len = 0; + + r = chash_set(privacy->mmapstr, &key, &data, NULL); + if (r < 0) + return MAIL_ERROR_MEMORY; + + return 0; +} + +static void unregister_result_mmapstr(struct mailprivacy * privacy, + char * str) +{ + chashdatum key; + + mmap_string_unref(str); + + key.data = &str; + key.len = sizeof(str); + + chash_delete(privacy->mmapstr, &key, NULL); +} + +static int register_mime(struct mailprivacy * privacy, + struct mailmime * mime) +{ + chashdatum key; + chashdatum data; + int r; + + key.data = &mime; + key.len = sizeof(mime); + data.data = mime; + data.len = 0; + + r = chash_set(privacy->mime_ref, &key, &data, NULL); + if (r < 0) + return MAIL_ERROR_MEMORY; + else + return MAIL_NO_ERROR; +} + +static void unregister_mime(struct mailprivacy * privacy, + struct mailmime * mime) +{ + chashdatum key; + + key.data = &mime; + key.len = sizeof(mime); + + chash_delete(privacy->mime_ref, &key, NULL); +} + +static int mime_is_registered(struct mailprivacy * privacy, + struct mailmime * mime) +{ + chashdatum key; + chashdatum data; + int r; + + key.data = &mime; + key.len = sizeof(mime); + + r = chash_get(privacy->mime_ref, &key, &data); + if (r < 0) + return 0; + else + return 1; +} + +static int recursive_register_mime(struct mailprivacy * privacy, + struct mailmime * mime) +{ + clistiter * cur; + int r; + + r = register_mime(privacy, mime); + if (r != MAIL_NO_ERROR) + return r; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + break; + + case MAILMIME_MULTIPLE: + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = clist_content(cur); + + r = recursive_register_mime(privacy, child); + if (r != MAIL_NO_ERROR) + return r; + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime) { + r = recursive_register_mime(privacy, + mime->mm_data.mm_message.mm_msg_mime); + if (r != MAIL_NO_ERROR) + return r; + } + break; + } + + return MAIL_NO_ERROR; +} + +void mailprivacy_recursive_unregister_mime(struct mailprivacy * privacy, + struct mailmime * mime) +{ + clistiter * cur; + + unregister_mime(privacy, mime); + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + break; + + case MAILMIME_MULTIPLE: + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = clist_content(cur); + + mailprivacy_recursive_unregister_mime(privacy, child); + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime) + mailprivacy_recursive_unregister_mime(privacy, + mime->mm_data.mm_message.mm_msg_mime); + break; + } +} + +static void recursive_clear_registered_mime(struct mailprivacy * privacy, + struct mailmime * mime) +{ + clistiter * cur; + struct mailmime_data * data; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + if (mime_is_registered(privacy, mime)) { + data = mime->mm_data.mm_single; + if (data != NULL) { + if (data->dt_type == MAILMIME_DATA_FILE) + unlink(data->dt_data.dt_filename); + } + } + break; + + case MAILMIME_MULTIPLE: + if (mime_is_registered(privacy, mime)) { + data = mime->mm_data.mm_multipart.mm_preamble; + if (data != NULL) { + if (data->dt_type == MAILMIME_DATA_FILE) + unlink(data->dt_data.dt_filename); + } + data = mime->mm_data.mm_multipart.mm_epilogue; + if (data != NULL) { + if (data->dt_type == MAILMIME_DATA_FILE) + unlink(data->dt_data.dt_filename); + } + } + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = clist_content(cur); + + recursive_clear_registered_mime(privacy, child); + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime) + recursive_clear_registered_mime(privacy, + mime->mm_data.mm_message.mm_msg_mime); + break; + } + unregister_mime(privacy, mime); +} + + +/* **************************************************** */ +/* fetch operations start here */ + + +static void recursive_clear_registered_mime(struct mailprivacy * privacy, + struct mailmime * mime); + +#if 0 +static void display_recursive_part(struct mailmime * mime) +{ + clistiter * cur; + + fprintf(stderr, "part %p\n", mime->mm_body); + switch (mime->mm_type) { + case MAILMIME_SINGLE: + fprintf(stderr, "single %p - %i\n", mime->mm_data.mm_single, + mime->mm_data.mm_single->dt_type); + if (mime->mm_data.mm_single->dt_type == MAILMIME_DATA_TEXT) { + fprintf(stderr, "data : %p %i\n", + mime->mm_data.mm_single->dt_data.dt_text.dt_data, + mime->mm_data.mm_single->dt_data.dt_text.dt_length); + } + break; + case MAILMIME_MESSAGE: + fprintf(stderr, "message %p\n", mime->mm_data.mm_message.mm_msg_mime); + display_recursive_part(mime->mm_data.mm_message.mm_msg_mime); + break; + case MAILMIME_MULTIPLE: + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; cur != NULL ; + cur = clist_next(cur)) { + + fprintf(stderr, "multipart\n"); + display_recursive_part(clist_content(cur)); + } + break; + } +} +#endif + +int mailprivacy_msg_get_bodystructure(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime ** result) +{ + int r; + struct mailmime * mime; + + if (msg_info->msg_mime != NULL) + return MAIL_NO_ERROR; + + if (msg_is_modified(privacy, msg_info)) + return MAIL_NO_ERROR; + + r = mailmessage_get_bodystructure(msg_info, &mime); + if (r != MAIL_NO_ERROR) + return r; + + /* modification on message if necessary */ + r = recursive_check_privacy(privacy, msg_info, msg_info->msg_mime); + if (r != MAIL_NO_ERROR) { + * result = msg_info->msg_mime; + return MAIL_NO_ERROR; + } + + r = register_msg(privacy, msg_info); + if (r != MAIL_NO_ERROR) { + recursive_clear_registered_mime(privacy, mime); + mailmessage_flush(msg_info); + return MAIL_ERROR_MEMORY; + } + + * result = msg_info->msg_mime; + + return MAIL_NO_ERROR; +} + +void mailprivacy_msg_flush(struct mailprivacy * privacy, + mailmessage * msg_info) +{ + if (msg_is_modified(privacy, msg_info)) { + /* remove all modified parts */ + if (msg_info->msg_mime != NULL) + recursive_clear_registered_mime(privacy, msg_info->msg_mime); + unregister_message(privacy, msg_info); + } + + mailmessage_flush(msg_info); +} + +static int fetch_registered_part(struct mailprivacy * privacy, + int (* fetch_section)(mailmessage *, struct mailmime *, + char **, size_t *), + struct mailmime * mime, + char ** result, size_t * result_len) +{ + mailmessage * dummy_msg; + int res; + char * content; + size_t content_len; + int r; + + dummy_msg = mime_message_init(NULL); + if (dummy_msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + r = mime_message_set_tmpdir(dummy_msg, privacy->tmp_dir); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto free_msg; + } + + r = fetch_section(dummy_msg, mime, &content, &content_len); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_msg; + } + + r = register_result_mmapstr(privacy, content); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_fetch; + } + + mailmessage_free(dummy_msg); + + * result = content; + * result_len = content_len; + + return MAIL_NO_ERROR; + + free_fetch: + mailmessage_fetch_result_free(dummy_msg, content); + free_msg: + mailmessage_free(dummy_msg); + err: + return res; +} + +int mailprivacy_msg_fetch_section(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len) +{ + if (msg_is_modified(privacy, msg_info) && + mime_is_registered(privacy, mime)) { + return fetch_registered_part(privacy, mailmessage_fetch_section, + mime, result, result_len); + } + + return mailmessage_fetch_section(msg_info, mime, result, result_len); +} + +int mailprivacy_msg_fetch_section_header(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + if (msg_is_modified(privacy, msg_info) && + mime_is_registered(privacy, mime)) { + return fetch_registered_part(privacy, mailmessage_fetch_section_header, + mime, result, result_len); + } + + return mailmessage_fetch_section_header(msg_info, mime, result, result_len); +} + +int mailprivacy_msg_fetch_section_mime(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + if (msg_is_modified(privacy, msg_info) && + mime_is_registered(privacy, mime)) { + return fetch_registered_part(privacy, mailmessage_fetch_section_mime, + mime, result, result_len); + } + + return mailmessage_fetch_section_mime(msg_info, mime, result, result_len); +} + +int mailprivacy_msg_fetch_section_body(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len) +{ + if (msg_is_modified(privacy, msg_info) && + mime_is_registered(privacy, mime)) { + return fetch_registered_part(privacy, mailmessage_fetch_section_body, + mime, result, result_len); + } + + return mailmessage_fetch_section_body(msg_info, mime, result, result_len); +} + +void mailprivacy_msg_fetch_result_free(struct mailprivacy * privacy, + mailmessage * msg_info, + char * msg) +{ + if (msg == NULL) + return; + + if (msg_is_modified(privacy, msg_info)) { + if (result_is_mmapstr(privacy, msg)) { + unregister_result_mmapstr(privacy, msg); + return; + } + } + + mailmessage_fetch_result_free(msg_info, msg); +} + +int mailprivacy_msg_fetch(struct mailprivacy * privacy, + mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + return mailmessage_fetch(msg_info, result, result_len); +} + +int mailprivacy_msg_fetch_header(struct mailprivacy * privacy, + mailmessage * msg_info, + char ** result, + size_t * result_len) +{ + return mailmessage_fetch_header(msg_info, result, result_len); +} + +/* end of fetch operations */ +/* **************************************************** */ + +static int privacy_handler(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result); + + + +static struct mailmime * +mime_add_alternative(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, + struct mailmime * alternative) +{ + struct mailmime * multipart; + int r; + struct mailmime * mime_copy; + char original_filename[PATH_MAX]; + + if (mime->mm_parent == NULL) + goto err; + + r = mailmime_new_with_content("multipart/alternative", NULL, &multipart); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = mailmime_smart_add_part(multipart, alternative); + if (r != MAILIMF_NO_ERROR) { + goto free_multipart; + } + + /* get copy of mime part "mime" and set parts */ + + r = mailprivacy_fetch_mime_body_to_file(privacy, + original_filename, sizeof(original_filename), + msg, mime); + if (r != MAIL_NO_ERROR) + goto detach_alternative; + + r = mailprivacy_get_part_from_file(privacy, 0, 0, + original_filename, &mime_copy); + unlink(original_filename); + if (r != MAIL_NO_ERROR) { + goto detach_alternative; + } + + r = mailmime_smart_add_part(multipart, mime_copy); + if (r != MAILIMF_NO_ERROR) { + goto free_mime_copy; + } + + r = recursive_register_mime(privacy, multipart); + if (r != MAIL_NO_ERROR) + goto detach_mime_copy; + + mailmime_substitute(mime, multipart); + + mailmime_free(mime); + + return multipart; + + detach_mime_copy: + mailprivacy_recursive_unregister_mime(privacy, multipart); + mailmime_remove_part(alternative); + free_mime_copy: + mailprivacy_mime_clear(mime_copy); + mailmime_free(mime_copy); + detach_alternative: + mailmime_remove_part(alternative); + free_multipart: + mailmime_free(multipart); + err: + return NULL; +} + +/* + recursive_check_privacy returns MAIL_NO_ERROR if at least one + part is using a privacy protocol. +*/ + +static int recursive_check_privacy(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime) +{ + int r; + clistiter * cur; + struct mailmime * alternative; + int res; + struct mailmime * multipart; + + if (privacy == NULL) + return MAIL_NO_ERROR; + + if (mime_is_registered(privacy, mime)) + return MAIL_ERROR_INVAL; + + r = privacy_handler(privacy, msg, mime, &alternative); + if (r == MAIL_NO_ERROR) { + if (privacy->make_alternative) { + multipart = mime_add_alternative(privacy, msg, mime, alternative); + if (multipart == NULL) { + mailprivacy_mime_clear(alternative); + mailmime_free(alternative); + return MAIL_ERROR_MEMORY; + } + } + else { + mailmime_substitute(mime, alternative); + mailmime_free(mime); + mime = NULL; + } + + return MAIL_NO_ERROR; + } + else { + switch (mime->mm_type) { + case MAILMIME_SINGLE: + return MAIL_ERROR_INVAL; + + case MAILMIME_MULTIPLE: + res = MAIL_ERROR_INVAL; + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = clist_content(cur); + + r = recursive_check_privacy(privacy, msg, child); + if (r == MAIL_NO_ERROR) + res = MAIL_NO_ERROR; + } + + return res; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime != NULL) + return recursive_check_privacy(privacy, msg, + mime->mm_data.mm_message.mm_msg_mime); + return MAIL_ERROR_INVAL; + + default: + return MAIL_ERROR_INVAL; + } + } +} + +static int privacy_handler(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + int r; + struct mailmime * alternative_mime; + unsigned int i; + + alternative_mime = NULL; + for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) { + struct mailprivacy_protocol * protocol; + + protocol = carray_get(privacy->protocols, i); + + if (protocol->decrypt != NULL) { + r = protocol->decrypt(privacy, msg, mime, &alternative_mime); + if (r == MAIL_NO_ERROR) { + + * result = alternative_mime; + + return MAIL_NO_ERROR; + } + } + } + + return MAIL_ERROR_INVAL; +} + +int mailprivacy_register(struct mailprivacy * privacy, + struct mailprivacy_protocol * protocol) +{ + int r; + + r = carray_add(privacy->protocols, protocol, NULL); + if (r < 0) + return MAIL_ERROR_MEMORY; + + return MAIL_NO_ERROR; +} + +void mailprivacy_unregister(struct mailprivacy * privacy, + struct mailprivacy_protocol * protocol) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) { + if (carray_get(privacy->protocols, i) == protocol) { + carray_delete(privacy->protocols, i); + return; + } + } +} + +static struct mailprivacy_protocol * +get_protocol(struct mailprivacy * privacy, char * privacy_driver) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) { + struct mailprivacy_protocol * protocol; + + protocol = carray_get(privacy->protocols, i); + if (strcasecmp(protocol->name, privacy_driver) == 0) + return protocol; + } + + return NULL; +} + +static struct mailprivacy_encryption * +get_encryption(struct mailprivacy_protocol * protocol, + char * privacy_encryption) +{ + int i; + + for(i = 0 ; i < protocol->encryption_count ; i ++) { + struct mailprivacy_encryption * encryption; + + encryption = &protocol->encryption_tab[i]; + if (strcasecmp(encryption->name, privacy_encryption) == 0) + return encryption; + } + + return NULL; +} + +int mailprivacy_encrypt(struct mailprivacy * privacy, + char * privacy_driver, char * privacy_encryption, + struct mailmime * mime, + struct mailmime ** result) +{ + return mailprivacy_encrypt_msg(privacy, privacy_driver, privacy_encryption, + NULL, mime, result); +} + +int mailprivacy_encrypt_msg(struct mailprivacy * privacy, + char * privacy_driver, char * privacy_encryption, + mailmessage * msg, + struct mailmime * mime, + struct mailmime ** result) +{ + struct mailprivacy_protocol * protocol; + struct mailprivacy_encryption * encryption; + int r; + + protocol = get_protocol(privacy, privacy_driver); + if (protocol == NULL) + return MAIL_ERROR_INVAL; + + encryption = get_encryption(protocol, privacy_encryption); + if (encryption == NULL) + return MAIL_ERROR_INVAL; + + if (encryption->encrypt == NULL) + return MAIL_ERROR_NOT_IMPLEMENTED; + + r = encryption->encrypt(privacy, msg, mime, result); + if (r != MAIL_NO_ERROR) + return r; + + return MAIL_NO_ERROR; +} + +char * mailprivacy_get_encryption_name(struct mailprivacy * privacy, + char * privacy_driver, char * privacy_encryption) +{ + struct mailprivacy_protocol * protocol; + struct mailprivacy_encryption * encryption; + + protocol = get_protocol(privacy, privacy_driver); + if (protocol == NULL) + return NULL; + + encryption = get_encryption(protocol, privacy_encryption); + if (encryption == NULL) + return NULL; + + return encryption->description; +} + +int mailprivacy_is_encrypted(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime) +{ + unsigned int i; + + if (mime_is_registered(privacy, mime)) + return 0; + + for(i = 0 ; i < carray_count(privacy->protocols) ; i ++) { + struct mailprivacy_protocol * protocol; + + protocol = carray_get(privacy->protocols, i); + + if (protocol->is_encrypted != NULL) { + if (protocol->is_encrypted(privacy, msg, mime)) + return 1; + } + } + + return 0; +} + +void mailprivacy_debug(struct mailprivacy * privacy, FILE * f) +{ + fprintf(f, "privacy debug -- begin\n"); + fprintf(f, "registered message: %i\n", chash_count(privacy->msg_ref)); + fprintf(f, "registered MMAPStr: %i\n", chash_count(privacy->mmapstr)); + fprintf(f, "registered mailmime: %i\n", chash_count(privacy->mime_ref)); + fprintf(f, "privacy debug -- end\n"); +} Added: freeswitch/trunk/libs/libetpan/src/engine/mailprivacy.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/engine/mailprivacy.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,125 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy.h,v 1.4 2005/11/21 16:17:57 hoa Exp $ + */ + +#ifndef MAILPRIVACY_H + +#define MAILPRIVACY_H + +#include <libetpan/mailmessage.h> +#include <libetpan/mailprivacy_types.h> +#include <libetpan/mailprivacy_tools.h> + +struct mailprivacy * mailprivacy_new(char * tmp_dir, int make_alternative); + +void mailprivacy_free(struct mailprivacy * privacy); + +int mailprivacy_msg_get_bodystructure(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime ** result); + +void mailprivacy_msg_flush(struct mailprivacy * privacy, + mailmessage * msg_info); + +int mailprivacy_msg_fetch_section(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, size_t * result_len); + +int mailprivacy_msg_fetch_section_header(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +int mailprivacy_msg_fetch_section_mime(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +int mailprivacy_msg_fetch_section_body(struct mailprivacy * privacy, + mailmessage * msg_info, + struct mailmime * mime, + char ** result, + size_t * result_len); + +void mailprivacy_msg_fetch_result_free(struct mailprivacy * privacy, + mailmessage * msg_info, + char * msg); + +int mailprivacy_msg_fetch(struct mailprivacy * privacy, + mailmessage * msg_info, + char ** result, + size_t * result_len); + +int mailprivacy_msg_fetch_header(struct mailprivacy * privacy, + mailmessage * msg_info, + char ** result, + size_t * result_len); + +int mailprivacy_register(struct mailprivacy * privacy, + struct mailprivacy_protocol * protocol); + +void mailprivacy_unregister(struct mailprivacy * privacy, + struct mailprivacy_protocol * protocol); + +char * mailprivacy_get_encryption_name(struct mailprivacy * privacy, + char * privacy_driver, char * privacy_encryption); + +/* deprecated */ +int mailprivacy_encrypt(struct mailprivacy * privacy, + char * privacy_driver, char * privacy_encryption, + struct mailmime * mime, + struct mailmime ** result); + +/* introduced the use of passphrase */ +int mailprivacy_encrypt_msg(struct mailprivacy * privacy, + char * privacy_driver, char * privacy_encryption, + mailmessage * msg, + struct mailmime * mime, + struct mailmime ** result); + +void mailprivacy_debug(struct mailprivacy * privacy, FILE * f); + +carray * mailprivacy_get_protocols(struct mailprivacy * privacy); + +int mailprivacy_is_encrypted(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime); + +void mailprivacy_recursive_unregister_mime(struct mailprivacy * privacy, + struct mailmime * mime); + +#endif Added: freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_gnupg.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_gnupg.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3156 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_gnupg.c,v 1.10 2006/06/26 11:50:27 hoa Exp $ + */ + +/* passphrase is needed when private key is needed + private key is needed : + - to sign a message + - and to decrypt a message +*/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailprivacy_gnupg.h" + +#include "mailprivacy.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> +#include <string.h> +#include <sys/wait.h> +#include <stdlib.h> +#include "mailprivacy_tools.h" +#include <libetpan/mailmime.h> +#include <libetpan/libetpan-config.h> +#ifdef LIBETPAN_REENTRANT +#include <pthread.h> +#endif +#include <ctype.h> + + +enum { + NO_ERROR_PGP = 0, + ERROR_PGP_CHECK, + ERROR_PGP_COMMAND, + ERROR_PGP_FILE, + ERROR_PGP_NOPASSPHRASE +}; + +static int mailprivacy_gnupg_add_encryption_id(struct mailprivacy * privacy, + mailmessage * msg, char * encryption_id); +static char * get_passphrase(struct mailprivacy * privacy, + char * user_id); +static int get_userid(char * filename, char * username, size_t length); + +static int gpg_command_passphrase(struct mailprivacy * privacy, + struct mailmessage * msg, + char * command, char * userid, + char * stdoutfile, char * stderrfile) +{ + pid_t pid; + int passphrase_input[2]; + int fd_err; + int fd_out; + int r; + char * passphrase; + int bad_passphrase; + int res; + + bad_passphrase = 0; + + passphrase = NULL; + if (userid != NULL) + passphrase = get_passphrase(privacy, userid); + + fd_out = open(stdoutfile, O_RDWR | O_CREAT | O_TRUNC, 0600); + if (fd_out < 0) { + res = ERROR_PGP_FILE; + goto err; + } + + fd_err = open(stderrfile, O_RDWR | O_CREAT | O_TRUNC, 0600); + if (fd_err < 0) { + res = ERROR_PGP_FILE; + goto close_out; + } + + r = pipe(passphrase_input); + if (r < 0) { + res = ERROR_PGP_FILE; + goto close_err; + } + + pid = fork(); + switch (pid) { + case -1: + return ERROR_PGP_COMMAND; + + case 0: + /* child */ + { + int status; + + /* close unneeded fd */ + close(passphrase_input[1]); + + dup2(passphrase_input[0], 0); + close(passphrase_input[0]); + dup2(fd_out, 1); + close(fd_out); + dup2(fd_err, 2); + close(fd_err); + + status = system(command); + + exit(WEXITSTATUS(status)); + } + break; + + default: + /* parent */ + { + int status; + + /* close unneeded fd */ + close(fd_err); + close(fd_out); + close(passphrase_input[0]); + + if (passphrase != NULL) { + write(passphrase_input[1], passphrase, strlen(passphrase)); + } + close(passphrase_input[1]); + + waitpid(pid, &status, 0); + + if (WEXITSTATUS(status) != 0) + bad_passphrase = 1; + } + break; + } + + if (bad_passphrase && (userid == NULL)) { + char encryption_id[4096]; + + encryption_id[0] = '\0'; + r = get_userid(stderrfile, encryption_id, sizeof(encryption_id)); + if (r == 0) { + passphrase = get_passphrase(privacy, encryption_id); + if (passphrase == NULL) { + mailprivacy_gnupg_add_encryption_id(privacy, msg, encryption_id); + return ERROR_PGP_NOPASSPHRASE; + } + else { + return gpg_command_passphrase(privacy, msg, command, encryption_id, + stdoutfile, stderrfile); + } + } + else { + return ERROR_PGP_CHECK; + } + } + + if (bad_passphrase && (passphrase != NULL)) { + return ERROR_PGP_CHECK; + } + + if (bad_passphrase) { + mailprivacy_gnupg_add_encryption_id(privacy, msg, userid); + return ERROR_PGP_NOPASSPHRASE; + } + + return NO_ERROR_PGP; + + close_err: + close(fd_err); + close_out: + close(fd_out); + err: + return res; +} + +static int pgp_is_encrypted(struct mailmime * mime) +{ + if (mime->mm_content_type != NULL) { + clistiter * cur; + + if (strcasecmp(mime->mm_content_type->ct_subtype, "encrypted") != 0) + return 0; + + for(cur = clist_begin(mime->mm_content_type->ct_parameters) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + + if ((strcasecmp(param->pa_name, "protocol") == 0) && + (strcasecmp(param->pa_value, "application/pgp-encrypted") == 0)) + return 1; + } + } + + return 0; +} + +static int pgp_is_signed(struct mailmime * mime) +{ + if (mime->mm_content_type != NULL) { + clistiter * cur; + + if (strcasecmp(mime->mm_content_type->ct_subtype, "signed") != 0) + return 0; + + for(cur = clist_begin(mime->mm_content_type->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + + if ((strcasecmp(param->pa_name, "protocol") == 0) && + (strcasecmp(param->pa_value, "application/pgp-signature") == 0)) + return 1; + } + } + + return 0; +} + +#define PGP_SIGNED "-----BEGIN PGP SIGNED MESSAGE-----" + +int pgp_is_clearsigned(char * data, size_t len) +{ + if (len >= strlen(PGP_SIGNED)) + if (strncmp(data, PGP_SIGNED, sizeof(PGP_SIGNED) - 1) == 0) + return 1; + + return 0; +} + +#define PGP_CRYPTED "-----BEGIN PGP MESSAGE-----" + +int pgp_is_crypted_armor(char * data, size_t len) +{ + if (len >= strlen(PGP_CRYPTED)) + if (strncmp(data, PGP_CRYPTED, sizeof(PGP_CRYPTED) - 1) == 0) + return 1; + + return 0; +} + + +#if 0 +#define BUF_SIZE 1024 + +/* write output to a file */ + +static int get_pgp_output(FILE * dest_f, char * command) +{ + FILE * p; + char buf[BUF_SIZE]; + size_t size; + int res; + int status; + char command_redirected[PATH_MAX]; + + snprintf(command_redirected, sizeof(command_redirected), "%s 2>&1", command); + + /* + flush buffer so that it is not flushed more than once when forking + */ + fflush(dest_f); + + p = popen(command_redirected, "r"); + if (p == NULL) { + res = ERROR_PGP_COMMAND; + goto err; + } + + while ((size = fread(buf, 1, sizeof(buf), p)) != 0) { + size_t written; + + written = fwrite(buf, 1, size, dest_f); + if (written != size) { + res = ERROR_PGP_FILE; + goto close; + } + } + status = pclose(p); + + if (WEXITSTATUS(status) != 0) + return ERROR_PGP_CHECK; + else + return NO_ERROR_PGP; + + close: + pclose(p); + err: + return res; +} +#endif + +/* parse output */ + +enum { + STATE_USERID, + STATE_NORMAL +}; + +static int get_userid(char * filename, char * username, size_t length) +{ + FILE * f; + int state; + char buffer[4096]; + int exit_code; + + exit_code = -1; + + f = fopen(filename, "r"); + if (f == NULL) + goto exit; + + state = STATE_NORMAL; + while (fgets(buffer, sizeof(buffer), f) != NULL) { + + switch (state) { + case STATE_NORMAL: + if (strncmp(buffer, "gpg: encrypted", 14) == 0) + state = STATE_USERID; + break; + + case STATE_USERID: + { + struct mailimf_mailbox * mb; + size_t current_index; + int r; + size_t buflen; + size_t i; + char * beginning; + + /* find double-quotes and remove beginning and ending */ + + buflen = strlen(buffer); + for(i = buflen - 1 ; 1 ; i --) { + if (buffer[i] == '\"') { + buffer[i] = '\0'; + break; + } + + if (i == 0) + break; + } + + beginning = buffer; + for(i = 0 ; i < buflen ; i ++) { + if (buffer[i] == '\"') { + beginning = buffer + i + 1; + break; + } + } + + r = mailimf_mailbox_parse(beginning, strlen(beginning), + ¤t_index, &mb); + if (r == MAILIMF_NO_ERROR) { + strncpy(username, mb->mb_addr_spec, length); + username[length - 1] = '\0'; + mailimf_mailbox_free(mb); + exit_code = 0; + } + + state = STATE_NORMAL; + } + break; + } + } + + fclose(f); + + exit: + return exit_code; +} + +#define PGP_DECRYPT_DESCRIPTION "PGP encrypted part\r\n" +#define PGP_DECRYPT_FAILED "PGP decryption FAILED\r\n" +#define PGP_DECRYPT_SUCCESS "PGP decryption success\r\n" + +/* extracted from mailprivacy_smime.c -- begin */ + +static char * get_first_from_addr(struct mailmime * mime) +{ + clistiter * cur; + struct mailimf_single_fields single_fields; + struct mailimf_fields * fields; + struct mailimf_mailbox * mb; + + if (mime->mm_type != MAILMIME_MESSAGE) + return NULL; + + fields = mime->mm_data.mm_message.mm_fields; + if (fields == NULL) + return NULL; + + mailimf_single_fields_init(&single_fields, fields); + + if (single_fields.fld_from == NULL) + return NULL; + + cur = clist_begin(single_fields.fld_from->frm_mb_list->mb_list); + if (cur == NULL) + return NULL; + + mb = clist_content(cur); + + return mb->mb_addr_spec; +} + +/* extracted from mailprivacy_smime.c -- end */ + +static int pgp_decrypt(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + struct mailmime * version_mime; + struct mailmime * encrypted_mime; + clistiter * cur; + char encrypted_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char decrypted_filename[PATH_MAX]; + char command[PATH_MAX]; + struct mailmime * description_mime; + struct mailmime * decrypted_mime; + int r; + int res; + int decrypt_ok; + char quoted_encrypted_filename[PATH_MAX]; + struct mailmime * multipart; + + /* get the two parts of the PGP message */ + + cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list); + if (cur == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + version_mime = clist_content(cur); + cur = clist_next(cur); + if (cur == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + encrypted_mime = clist_content(cur); + + /* fetch the second section, that's the useful one */ + + r = mailprivacy_fetch_decoded_to_file(privacy, + encrypted_filename, sizeof(encrypted_filename), + msg, encrypted_mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + /* we are in a safe directory */ + + r = mailprivacy_get_tmp_filename(privacy, + decrypted_filename, sizeof(decrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_encrypted; + } + + /* description */ + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_decrypted; + } + + /* run the command */ + + r = mail_quote_filename(quoted_encrypted_filename, + sizeof(quoted_encrypted_filename), encrypted_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), + "gpg --passphrase-fd=0 --batch --yes --decrypt '%s'", + quoted_encrypted_filename); + + decrypt_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + decrypted_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + decrypt_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + decrypt_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (!decrypt_ok) { + char encryption_id[4096]; + + encryption_id[0] = '\0'; + r = get_userid(description_filename, encryption_id, sizeof(encryption_id)); + if (r == 0) { + mailprivacy_gnupg_add_encryption_id(privacy, msg, encryption_id); + } + } + + /* building multipart */ + + r = mailmime_new_with_content("multipart/x-decrypted", NULL, &multipart); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the description part */ + + description_mime = mailprivacy_new_file_part(privacy, + description_filename, + "text/plain", MAILMIME_MECHANISM_8BIT); + if (description_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* adds the description part */ + + r = mailmime_smart_add_part(multipart, description_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(description_mime); + mailmime_free(description_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the decrypted part */ + + r = mailprivacy_get_part_from_file(privacy, 1, 0, + decrypted_filename, &decrypted_mime); + if (r == MAIL_NO_ERROR) { + /* adds the decrypted part */ + + r = mailmime_smart_add_part(multipart, decrypted_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(decrypted_mime); + mailmime_free(decrypted_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + } + + unlink(description_filename); + unlink(decrypted_filename); + unlink(encrypted_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_decrypted: + unlink(decrypted_filename); + unlink_encrypted: + unlink(encrypted_filename); + err: + return res; +} + +#define PGP_VERIFY_DESCRIPTION "PGP verify signed message\r\n" +#define PGP_VERIFY_FAILED "PGP verification FAILED\r\n" +#define PGP_VERIFY_SUCCESS "PGP verification success\r\n" + +static int +pgp_verify(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + struct mailmime * signed_mime; + struct mailmime * signature_mime; + char signed_filename[PATH_MAX]; + char signature_filename[PATH_MAX]; + int res; + int r; + clistiter * cur; + char command[PATH_MAX]; + int sign_ok; + struct mailmime * description_mime; + char decrypted_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char quoted_signed_filename[PATH_MAX]; + char quoted_signature_filename[PATH_MAX]; + struct mailmime * multipart; + struct mailmime * signed_msg_mime; + + /* get the two parts of the PGP message */ + + cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list); + if (cur == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + signed_mime = clist_content(cur); + cur = clist_next(cur); + if (cur == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + signature_mime = clist_content(cur); + + /* fetch signed part and write it to a file */ + + r = mailprivacy_fetch_mime_body_to_file(privacy, + signed_filename, sizeof(signed_filename), + msg, signed_mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + /* fetch signed part and write it to a file */ + + r = mailprivacy_fetch_decoded_to_file(privacy, + signature_filename, sizeof(signature_filename), + msg, signature_mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_signed; + } + + /* description */ + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_signature; + } + + /* decrypted (dummy) */ + + r = mailprivacy_get_tmp_filename(privacy, decrypted_filename, + sizeof(decrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_description; + } + + /* run the command */ + + r = mail_quote_filename(quoted_signature_filename, + sizeof(quoted_signature_filename), signature_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_decrypted; + } + + r = mail_quote_filename(quoted_signed_filename, + sizeof(quoted_signed_filename), signed_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_decrypted; + } + + snprintf(command, sizeof(command), "gpg --batch --yes --verify '%s' '%s'", + quoted_signature_filename, quoted_signed_filename); + + sign_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + decrypted_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + sign_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + sign_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_decrypted; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_decrypted; + } + + /* building multipart */ + + r = mailmime_new_with_content("multipart/x-verified", NULL, &multipart); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto unlink_decrypted; + } + + /* building the description part */ + + description_mime = mailprivacy_new_file_part(privacy, + description_filename, + "text/plain", MAILMIME_MECHANISM_8BIT); + if (description_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_decrypted; + } + + /* adds the description part */ + + r = mailmime_smart_add_part(multipart, description_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(description_mime); + mailmime_free(description_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_decrypted; + } + + r = mailprivacy_get_part_from_file(privacy, 1, 0, + signed_filename, &signed_msg_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_decrypted; + } + + r = mailmime_smart_add_part(multipart, signed_msg_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(signed_msg_mime); + mailmime_free(signed_msg_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_decrypted; + } + + unlink(decrypted_filename); + unlink(description_filename); + unlink(signature_filename); + unlink(signed_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_decrypted: + unlink(decrypted_filename); + unlink_description: + unlink(description_filename); + unlink_signature: + unlink(signature_filename); + unlink_signed: + unlink(signed_filename); + err: + return res; +} + + +#define PGP_CLEAR_VERIFY_DESCRIPTION "PGP verify clear signed message\r\n" +#define PGP_CLEAR_VERIFY_FAILED "PGP verification FAILED\r\n" +#define PGP_CLEAR_VERIFY_SUCCESS "PGP verification success\r\n" + +static int pgp_verify_clearsigned(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, + char * content, size_t content_len, struct mailmime ** result) +{ + int r; + char command[PATH_MAX]; + int res; + int sign_ok; + size_t written; + char signed_filename[PATH_MAX]; + FILE * signed_f; + char stripped_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char quoted_signed_filename[PATH_MAX]; + struct mailmime * stripped_mime; + struct mailmime * description_mime; + struct mailmime * multipart; + struct mailmime_content * content_type; + + if (mime->mm_parent == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + if (mime->mm_parent->mm_type == MAILMIME_SINGLE) { + res = MAIL_ERROR_INVAL; + goto err; + } + + signed_f = mailprivacy_get_tmp_file(privacy, + signed_filename, sizeof(signed_filename)); + if (signed_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + written = fwrite(content, 1, content_len, signed_f); + if (written != content_len) { + fclose(signed_f); + unlink(signed_filename); + res = MAIL_ERROR_FILE; + goto err; + } + fclose(signed_f); + + /* XXX - prepare file for PGP, remove trailing WS */ + + r = mailprivacy_get_tmp_filename(privacy, stripped_filename, + sizeof(stripped_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_signed; + } + + /* description */ + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_stripped; + } + + r = mail_quote_filename(quoted_signed_filename, + sizeof(quoted_signed_filename), signed_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), + "gpg --batch --yes --decrypt '%s'", quoted_signed_filename); + + sign_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + stripped_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + sign_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + sign_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + /* building multipart */ + + r = mailmime_new_with_content("multipart/x-verified", NULL, &multipart); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the description part */ + + description_mime = mailprivacy_new_file_part(privacy, + description_filename, + "text/plain", MAILMIME_MECHANISM_8BIT); + if (description_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* adds the description part */ + + r = mailmime_smart_add_part(multipart, description_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(description_mime); + mailmime_free(description_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the signature stripped part */ + + stripped_mime = mailprivacy_new_file_part(privacy, + stripped_filename, + "application/octet-stream", + MAILMIME_MECHANISM_8BIT); + if (stripped_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* place original content type */ + + content_type = mailmime_content_dup(mime->mm_content_type); + if (content_type == NULL) { + mailprivacy_mime_clear(stripped_mime); + mailmime_free(stripped_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + mailmime_content_free(stripped_mime->mm_content_type); + stripped_mime->mm_content_type = content_type; + + /* place original MIME fields */ + + if (mime->mm_mime_fields != NULL) { + struct mailmime_fields * mime_fields; + clistiter * cur; + + mime_fields = mailprivacy_mime_fields_dup(privacy, mime->mm_mime_fields); + if (mime_fields == NULL) { + mailprivacy_mime_clear(stripped_mime); + mailmime_free(stripped_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + for(cur = clist_begin(mime_fields->fld_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) { + mailmime_field_free(field); + clist_delete(mime_fields->fld_list, cur); + break; + } + } + clist_concat(stripped_mime->mm_mime_fields->fld_list, + mime_fields->fld_list); + mailmime_fields_free(mime_fields); + } + + /* adds the stripped part */ + + r = mailmime_smart_add_part(multipart, stripped_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(stripped_mime); + mailmime_free(stripped_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + unlink(description_filename); + unlink(stripped_filename); + unlink(signed_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_stripped: + unlink(stripped_filename); + unlink_signed: + unlink(signed_filename); + err: + return res; +} + + +#define PGP_DECRYPT_ARMOR_DESCRIPTION "PGP ASCII armor encrypted part\r\n" +#define PGP_DECRYPT_ARMOR_FAILED "PGP ASCII armor decryption FAILED\r\n" +#define PGP_DECRYPT_ARMOR_SUCCESS "PGP ASCII armor decryption success\r\n" + +static int pgp_decrypt_armor(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, + char * content, size_t content_len, struct mailmime ** result) +{ + FILE * encrypted_f; + char encrypted_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char decrypted_filename[PATH_MAX]; + size_t written; + char command[PATH_MAX]; + struct mailmime * description_mime; + struct mailmime * decrypted_mime; + struct mailmime * multipart; + int r; + int res; + int sign_ok; + char quoted_encrypted_filename[PATH_MAX]; + + if (mime->mm_parent == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + if (mime->mm_parent->mm_type == MAILMIME_SINGLE) { + res = MAIL_ERROR_INVAL; + goto err; + } + + encrypted_f = mailprivacy_get_tmp_file(privacy, + encrypted_filename, + sizeof(encrypted_filename)); + if (encrypted_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + written = fwrite(content, 1, content_len, encrypted_f); + if (written != content_len) { + fclose(encrypted_f); + unlink(encrypted_filename); + res = MAIL_ERROR_FILE; + goto err; + } + + fclose(encrypted_f); + + /* we are in a safe directory */ + + r = mailprivacy_get_tmp_filename(privacy, decrypted_filename, + sizeof(decrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_encrypted; + } + + /* description */ + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_decrypted; + } + + /* run the command */ + + r = mail_quote_filename(quoted_encrypted_filename, + sizeof(quoted_encrypted_filename), encrypted_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), + "gpg --passphrase-fd=0 --batch --yes --decrypt '%s'", + quoted_encrypted_filename); + + sign_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + decrypted_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + sign_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + sign_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + /* building multipart */ + + r = mailmime_new_with_content("multipart/x-decrypted", NULL, &multipart); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the description part */ + + description_mime = mailprivacy_new_file_part(privacy, + description_filename, + "text/plain", MAILMIME_MECHANISM_8BIT); + if (description_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* adds the description part */ + + r = mailmime_smart_add_part(multipart, description_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(description_mime); + mailmime_free(description_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the decrypted part */ + + r = mailprivacy_get_part_from_file(privacy, 1, 0, + decrypted_filename, &decrypted_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = r; + goto unlink_description; + } + + /* adds the decrypted part */ + + r = mailmime_smart_add_part(multipart, decrypted_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(decrypted_mime); + mailmime_free(decrypted_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + unlink(description_filename); + unlink(decrypted_filename); + unlink(encrypted_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_decrypted: + unlink(decrypted_filename); + unlink_encrypted: + unlink(encrypted_filename); + err: + return res; +} + + +static int mime_is_text(struct mailmime * build_info) +{ + if (build_info->mm_type == MAILMIME_SINGLE) { + if (build_info->mm_content_type != NULL) { + if (build_info->mm_content_type->ct_type->tp_type == + MAILMIME_TYPE_DISCRETE_TYPE) { + if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type == + MAILMIME_DISCRETE_TYPE_TEXT) + return 1; + } + } + else + return 1; + } + + return 0; +} + + +static int pgp_test_encrypted(struct mailprivacy * privacy, + mailmessage * msg, struct mailmime * mime) +{ + int r; + int res; + + switch (mime->mm_type) { + case MAILMIME_MULTIPLE: + return (pgp_is_encrypted(mime) || pgp_is_signed(mime)); + + case MAILMIME_SINGLE: + /* clear sign or ASCII armor encryption */ + if (mime_is_text(mime)) { + char * content; + size_t content_len; + char * parsed_content; + size_t parsed_content_len; + size_t cur_token; + int encoding; + struct mailmime_single_fields single_fields; + + r = mailprivacy_msg_fetch_section(privacy, msg, mime, + &content, &content_len); + if (r != MAIL_NO_ERROR) + return 0; + + mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, + mime->mm_content_type); + if (single_fields.fld_encoding != NULL) + encoding = single_fields.fld_encoding->enc_type; + else + encoding = MAILMIME_MECHANISM_8BIT; + + cur_token = 0; + r = mailmime_part_parse(content, content_len, &cur_token, + encoding, &parsed_content, &parsed_content_len); + mailprivacy_msg_fetch_result_free(privacy, msg, content); + + if (r != MAILIMF_NO_ERROR) + return 0; + + res = 0; + + if (pgp_is_clearsigned(parsed_content, parsed_content_len)) + res = 1; + else if (pgp_is_crypted_armor(parsed_content, parsed_content_len)) + res = 1; + + mmap_string_unref(parsed_content); + + return res; + } + break; + } + + return 0; +} + +static int pgp_handler(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + int r; + struct mailmime * alternative_mime; + + alternative_mime = NULL; + switch (mime->mm_type) { + case MAILMIME_MULTIPLE: + r = MAIL_ERROR_INVAL; + if (pgp_is_encrypted(mime)) { + r = pgp_decrypt(privacy, msg, mime, &alternative_mime); + } + else if (pgp_is_signed(mime)) { + r = pgp_verify(privacy, msg, mime, &alternative_mime); + } + + if (r != MAIL_NO_ERROR) + return r; + + * result = alternative_mime; + + return MAIL_NO_ERROR; + + case MAILMIME_SINGLE: + /* clear sign or ASCII armor encryption */ + if (mime_is_text(mime)) { + char * content; + size_t content_len; + char * parsed_content; + size_t parsed_content_len; + size_t cur_token; + int encoding; + struct mailmime_single_fields single_fields; + + r = mailprivacy_msg_fetch_section(privacy, msg, mime, + &content, &content_len); + if (r != MAIL_NO_ERROR) + return MAIL_ERROR_FETCH; + + mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, + mime->mm_content_type); + if (single_fields.fld_encoding != NULL) + encoding = single_fields.fld_encoding->enc_type; + else + encoding = MAILMIME_MECHANISM_8BIT; + + cur_token = 0; + r = mailmime_part_parse(content, content_len, &cur_token, + encoding, &parsed_content, &parsed_content_len); + mailprivacy_msg_fetch_result_free(privacy, msg, content); + + if (r != MAILIMF_NO_ERROR) + return MAIL_ERROR_PARSE; + + r = MAIL_ERROR_INVAL; + if (pgp_is_clearsigned(parsed_content, + parsed_content_len)) { + r = pgp_verify_clearsigned(privacy, + msg, mime, parsed_content, parsed_content_len, &alternative_mime); + } + else if (pgp_is_crypted_armor(parsed_content, + parsed_content_len)) { + r = pgp_decrypt_armor(privacy, + msg, mime, parsed_content, parsed_content_len, &alternative_mime); + } + + mmap_string_unref(parsed_content); + + if (r != MAIL_NO_ERROR) + return r; + + * result = alternative_mime; + + return MAIL_NO_ERROR; + } + break; + } + + return MAIL_ERROR_INVAL; +} + + +#if 0 +static void prepare_mime_single(struct mailmime * mime) +{ + struct mailmime_single_fields single_fields; + int encoding; + int r; + + if (mime->mime_fields != NULL) { + mailmime_single_fields_init(&single_fields, mime->mime_fields, + mime->content_type); + if (single_fields.encoding != NULL) { + encoding = single_fields.encoding->type; + switch (encoding) { + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_BINARY: + single_fields.encoding->type = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + break; + } + } + else { + struct mailmime_mechanism * mechanism; + struct mailmime_field * field; + + mechanism = + mailmime_mechanism_new(MAILMIME_MECHANISM_QUOTED_PRINTABLE, NULL); + if (mechanism == NULL) + return; + + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, mechanism, NULL, NULL, 0, NULL, NULL); + if (field == NULL) { + mailmime_mechanism_free(mechanism); + return; + } + + r = clist_append(mime->mime_fields->list, field); + if (r < 0) { + mailmime_field_free(field); + return; + } + } + } + + switch (mime->body->encoding) { + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_BINARY: + mime->body->encoding = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + mime->body->encoded = 0; + break; + } +} + +/* + prepare_mime() + + we assume we built ourself the message. +*/ + +static void prepare_mime(struct mailmime * mime) +{ + clistiter * cur; + + switch (mime->type) { + case MAILMIME_SINGLE: + if (mime->body != NULL) { + prepare_mime_single(mime); + } + break; + + case MAILMIME_MULTIPLE: + for(cur = clist_begin(mime->list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = cur->data; + + prepare_mime(child); + } + break; + + case MAILMIME_MESSAGE: + if (mime->msg_mime) { + prepare_mime(mime->msg_mime); + } + break; + } +} +#endif + +static int pgp_sign_mime(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char to_sign_filename[PATH_MAX]; + char quoted_to_sign_filename[PATH_MAX]; + FILE * to_sign_f; + int res; + int r; + int col; + char description_filename[PATH_MAX]; + char signature_filename[PATH_MAX]; + char command[PATH_MAX]; + char default_key[PATH_MAX]; + struct mailmime * signature_mime; + struct mailmime * multipart; + struct mailmime_content * content; + struct mailmime_parameter * param; + struct mailmime * to_sign_msg_mime; + char * dup_signature_filename; + char * email; + int sign_ok; + + /* get signing key */ + + * default_key = '\0'; + email = get_first_from_addr(mime); + if (email != NULL) + snprintf(default_key, sizeof(default_key), + "--default-key %s", email); + + /* part to sign */ + + /* encode quoted printable all text parts */ + + mailprivacy_prepare_mime(mime); + + to_sign_f = mailprivacy_get_tmp_file(privacy, + to_sign_filename, sizeof(to_sign_filename)); + if (to_sign_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_write(to_sign_f, &col, mime); + if (r != MAILIMF_NO_ERROR) { + fclose(to_sign_f); + res = MAIL_ERROR_FILE; + goto unlink_to_sign; + } + + fclose(to_sign_f); + + /* prepare destination file for signature */ + + r = mailprivacy_get_tmp_filename(privacy, signature_filename, + sizeof(signature_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_to_sign; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_signature; + } + + r = mail_quote_filename(quoted_to_sign_filename, + sizeof(quoted_to_sign_filename), to_sign_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), + "gpg --passphrase-fd=0 -a --batch --yes --digest-algo sha1 %s -b '%s'", + default_key, quoted_to_sign_filename); + + sign_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + signature_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + sign_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + sign_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (!sign_ok) { + res = MAIL_ERROR_COMMAND; + goto unlink_description; + } + + /* multipart */ + + multipart = mailprivacy_new_file_part(privacy, NULL, + "multipart/signed", -1); + + content = multipart->mm_content_type; + + param = mailmime_param_new_with_data("micalg", "pgp-sha1"); + if (param == NULL) { + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = clist_append(content->ct_parameters, param); + if (r < 0) { + mailmime_parameter_free(param); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + param = mailmime_param_new_with_data("protocol", + "application/pgp-signature"); + if (param == NULL) { + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = clist_append(content->ct_parameters, param); + if (r < 0) { + mailmime_parameter_free(param); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* signed part */ + + r = mailprivacy_get_part_from_file(privacy, 1, 0, + to_sign_filename, &to_sign_msg_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = r; + goto unlink_description; + } + + mailprivacy_prepare_mime(to_sign_msg_mime); + + r = mailmime_smart_add_part(multipart, to_sign_msg_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(to_sign_msg_mime); + mailmime_free(to_sign_msg_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* signature part */ + + /* reencode the signature file with CRLF */ + dup_signature_filename = mailprivacy_dup_imf_file(privacy, + signature_filename); + if (dup_signature_filename == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + /* replace the signature file */ + unlink(signature_filename); + strncpy(signature_filename, + dup_signature_filename, sizeof(signature_filename)); + signature_filename[sizeof(signature_filename) - 1] = '\0'; + + signature_mime = mailprivacy_new_file_part(privacy, + signature_filename, + "application/pgp-signature", + MAILMIME_MECHANISM_8BIT); + if (signature_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = mailmime_smart_add_part(multipart, signature_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(signature_mime); + mailmime_free(signature_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + unlink(description_filename); + unlink(signature_filename); + unlink(to_sign_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_signature: + unlink(signature_filename); + unlink_to_sign: + unlink(to_sign_filename); + err: + return res; +} + + +/* ********************************************************************* */ +/* find GPG recipient */ + +static int recipient_add_mb(char * recipient, size_t * len, + struct mailimf_mailbox * mb) +{ + char buffer[PATH_MAX]; + size_t buflen; + + if (mb->mb_addr_spec != NULL) { + snprintf(buffer, sizeof(buffer), "-r %s ", mb->mb_addr_spec); + buflen = strlen(buffer); + if (buflen >= * len) + return MAIL_ERROR_MEMORY; + + strncat(recipient, buffer, * len); + (* len) -= buflen; + } + + return MAIL_NO_ERROR; +} + +static int recipient_add_mb_list(char * recipient, size_t * len, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + r = recipient_add_mb(recipient, len, mb); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + +static int recipient_add_group(char * recipient, size_t * len, + struct mailimf_group * group) +{ + return recipient_add_mb_list(recipient, len, group->grp_mb_list); +} + +static int recipient_add_addr(char * recipient, size_t * len, + struct mailimf_address * addr) +{ + int r; + + switch (addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = recipient_add_mb(recipient, len, addr->ad_data.ad_mailbox); + break; + case MAILIMF_ADDRESS_GROUP: + r = recipient_add_group(recipient, len, addr->ad_data.ad_group); + break; + default: + r = MAIL_ERROR_INVAL; + } + + return r; +} + +static int recipient_add_addr_list(char * recipient, size_t * len, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + r = recipient_add_addr(recipient, len, addr); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + + +static int collect_recipient(char * recipient, size_t size, + struct mailimf_fields * fields) +{ + struct mailimf_single_fields single_fields; + int r; + size_t remaining; + int res; + + * recipient = '\0'; + remaining = size; + + if (fields != NULL) + mailimf_single_fields_init(&single_fields, fields); + + if (single_fields.fld_to != NULL) { + r = recipient_add_addr_list(recipient, &remaining, + single_fields.fld_to->to_addr_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + if (single_fields.fld_cc != NULL) { + r = recipient_add_addr_list(recipient, &remaining, + single_fields.fld_cc->cc_addr_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + if (single_fields.fld_bcc != NULL) { + if (single_fields.fld_bcc->bcc_addr_list != NULL) { + r = recipient_add_addr_list(recipient, &remaining, + single_fields.fld_bcc->bcc_addr_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + +#define PGP_VERSION "Version: 1\r\n" + +static int pgp_sign_encrypt_mime(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char original_filename[PATH_MAX]; + FILE * original_f; + int res; + int r; + int col; + char encrypted_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char version_filename[PATH_MAX]; + FILE * version_f; + char command[PATH_MAX]; + char quoted_original_filename[PATH_MAX]; + struct mailmime * version_mime; + struct mailmime * multipart; + struct mailmime_content * content; + struct mailmime_parameter * param; + struct mailmime * encrypted_mime; + char recipient[PATH_MAX]; + struct mailimf_fields * fields; + struct mailmime * root; + size_t written; + char * email; + int encrypt_ok; + char default_key[PATH_MAX]; + + /* get signing key */ + + * default_key = '\0'; + email = get_first_from_addr(mime); + if (email != NULL) + snprintf(default_key, sizeof(default_key), + "--default-key %s", email); + + root = mime; + while (root->mm_parent != NULL) + root = root->mm_parent; + + fields = NULL; + if (root->mm_type == MAILMIME_MESSAGE) + fields = root->mm_data.mm_message.mm_fields; + + /* recipient */ + + collect_recipient(recipient, sizeof(recipient), fields); + + /* part to encrypt */ + + /* encode quoted printable all text parts */ + + mailprivacy_prepare_mime(mime); + + original_f = mailprivacy_get_tmp_file(privacy, original_filename, + sizeof(original_filename)); + if (original_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_write(original_f, &col, mime); + if (r != MAILIMF_NO_ERROR) { + fclose(original_f); + res = MAIL_ERROR_FILE; + goto unlink_original; + } + + fclose(original_f); + + /* prepare destination file for encryption */ + + r = mailprivacy_get_tmp_filename(privacy, encrypted_filename, + sizeof(encrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_original; + } + + r = mail_quote_filename(quoted_original_filename, + sizeof(quoted_original_filename), original_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_encrypted; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_encrypted; + } + + snprintf(command, sizeof(command), + "gpg --passphrase-fd=0 %s -a --batch --yes --digest-algo sha1 -s %s -e '%s'", + recipient, default_key, quoted_original_filename); + + encrypt_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + encrypted_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + encrypt_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + encrypt_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (!encrypt_ok) { + res = MAIL_ERROR_COMMAND; + goto unlink_description; + } + + /* multipart */ + + multipart = mailprivacy_new_file_part(privacy, NULL, + "multipart/encrypted", -1); + + content = multipart->mm_content_type; + + param = mailmime_param_new_with_data("protocol", + "application/pgp-encrypted"); + if (param == NULL) { + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = clist_append(content->ct_parameters, param); + if (r < 0) { + mailmime_parameter_free(param); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* version part */ + + version_f = mailprivacy_get_tmp_file(privacy, + version_filename, + sizeof(version_filename)); + if (version_f == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_FILE; + goto unlink_description; + } + written = fwrite(PGP_VERSION, 1, sizeof(PGP_VERSION) - 1, version_f); + if (written != sizeof(PGP_VERSION) - 1) { + fclose(version_f); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_FILE; + goto unlink_description; + } + fclose(version_f); + + version_mime = mailprivacy_new_file_part(privacy, + version_filename, + "application/pgp-encrypted", + MAILMIME_MECHANISM_8BIT); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = r; + goto unlink_version; + } + + r = mailmime_smart_add_part(multipart, version_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(version_mime); + mailmime_free(version_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_version; + } + + /* encrypted part */ + + encrypted_mime = mailprivacy_new_file_part(privacy, + encrypted_filename, + "application/octet-stream", + MAILMIME_MECHANISM_8BIT); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = r; + goto unlink_version; + } + + r = mailmime_smart_add_part(multipart, encrypted_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(encrypted_mime); + mailmime_free(encrypted_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_version; + } + + unlink(version_filename); + unlink(description_filename); + unlink(encrypted_filename); + unlink(original_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_version: + unlink(version_filename); + unlink_description: + unlink(description_filename); + unlink_encrypted: + unlink(encrypted_filename); + unlink_original: + unlink(original_filename); + err: + return res; +} + + +static int pgp_encrypt_mime(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char original_filename[PATH_MAX]; + FILE * original_f; + int res; + int r; + int col; + char description_filename[PATH_MAX]; + char encrypted_filename[PATH_MAX]; + char version_filename[PATH_MAX]; + FILE * version_f; + char command[PATH_MAX]; + char quoted_original_filename[PATH_MAX]; + struct mailmime * version_mime; + struct mailmime * multipart; + struct mailmime_content * content; + struct mailmime_parameter * param; + struct mailmime * encrypted_mime; + char recipient[PATH_MAX]; + struct mailimf_fields * fields; + struct mailmime * root; + size_t written; + int encrypt_ok; + + root = mime; + while (root->mm_parent != NULL) + root = root->mm_parent; + + fields = NULL; + if (root->mm_type == MAILMIME_MESSAGE) + fields = root->mm_data.mm_message.mm_fields; + + /* recipient */ + + collect_recipient(recipient, sizeof(recipient), fields); + + /* part to encrypt */ + + /* encode quoted printable all text parts */ + + mailprivacy_prepare_mime(mime); + + original_f = mailprivacy_get_tmp_file(privacy, + original_filename, sizeof(original_filename)); + if (original_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_write(original_f, &col, mime); + if (r != MAILIMF_NO_ERROR) { + fclose(original_f); + res = MAIL_ERROR_FILE; + goto unlink_original; + } + + fclose(original_f); + + /* prepare destination file for encryption */ + + r = mailprivacy_get_tmp_filename(privacy, encrypted_filename, + sizeof(encrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_original; + } + + r = mail_quote_filename(quoted_original_filename, + sizeof(quoted_original_filename), original_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_encrypted; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_encrypted; + } + + snprintf(command, sizeof(command), "gpg %s -a --batch --yes -e '%s'", + recipient, quoted_original_filename); + + encrypt_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + encrypted_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + encrypt_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + encrypt_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (!encrypt_ok) { + res = MAIL_ERROR_COMMAND; + goto unlink_description; + } + + /* multipart */ + + multipart = mailprivacy_new_file_part(privacy, NULL, + "multipart/encrypted", -1); + + content = multipart->mm_content_type; + + param = mailmime_param_new_with_data("protocol", + "application/pgp-encrypted"); + if (param == NULL) { + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = clist_append(content->ct_parameters, param); + if (r < 0) { + mailmime_parameter_free(param); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* version part */ + + version_f = mailprivacy_get_tmp_file(privacy, + version_filename, sizeof(version_filename)); + if (version_f == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_FILE; + goto unlink_description; + } + written = fwrite(PGP_VERSION, 1, sizeof(PGP_VERSION) - 1, version_f); + if (written != sizeof(PGP_VERSION) - 1) { + fclose(version_f); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_FILE; + goto unlink_description; + } + fclose(version_f); + + version_mime = mailprivacy_new_file_part(privacy, + version_filename, + "application/pgp-encrypted", + MAILMIME_MECHANISM_8BIT); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = r; + goto unlink_version; + } + + r = mailmime_smart_add_part(multipart, version_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(version_mime); + mailmime_free(version_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_version; + } + + /* encrypted part */ + + encrypted_mime = mailprivacy_new_file_part(privacy, + encrypted_filename, + "application/octet-stream", + MAILMIME_MECHANISM_8BIT); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = r; + goto unlink_version; + } + + r = mailmime_smart_add_part(multipart, encrypted_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(encrypted_mime); + mailmime_free(encrypted_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_version; + } + + unlink(version_filename); + unlink(description_filename); + unlink(encrypted_filename); + unlink(original_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_version: + unlink(version_filename); + unlink_description: + unlink(description_filename); + unlink_encrypted: + unlink(encrypted_filename); + unlink_original: + unlink(original_filename); + err: + return res; +} + +static int pgp_clear_sign(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char default_key[PATH_MAX]; + char original_filename[PATH_MAX]; + FILE * original_f; + char signed_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char quoted_original_filename[PATH_MAX]; + int col; + struct mailmime * signed_mime; + int res; + int r; + char command[PATH_MAX]; + struct mailmime_content * content_type; + char * email; + int sign_ok; + + if (mime->mm_type != MAILMIME_SINGLE) { + res = MAIL_ERROR_INVAL; + goto err; + } + + if (mime->mm_data.mm_single == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + /* get signing key */ + + * default_key = '\0'; + email = get_first_from_addr(mime); + if (email != NULL) + snprintf(default_key, sizeof(default_key), + "--default-key %s", email); + + /* get part to sign */ + + original_f = mailprivacy_get_tmp_file(privacy, + original_filename, + sizeof(original_filename)); + if (original_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_data_write(original_f, &col, mime->mm_data.mm_single, 1); + if (r != MAILIMF_NO_ERROR) { + fclose(original_f); + res = MAIL_ERROR_FILE; + goto unlink_original; + } + fclose(original_f); + + r = mailprivacy_get_tmp_filename(privacy, signed_filename, + sizeof(signed_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_original; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_signed; + } + + r = mail_quote_filename(quoted_original_filename, + sizeof(quoted_original_filename), original_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), + "gpg --passphrase-fd=0 --batch --yes --digest-algo sha1 %s --clearsign '%s'", + default_key, quoted_original_filename); + + sign_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + signed_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + sign_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + sign_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (!sign_ok) { + res = MAIL_ERROR_COMMAND; + goto unlink_description; + } + + /* building the signed part */ + + signed_mime = mailprivacy_new_file_part(privacy, signed_filename, + NULL, MAILMIME_MECHANISM_8BIT); + if (signed_mime == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* place original content type */ + + content_type = mailmime_content_dup(mime->mm_content_type); + if (content_type == NULL) { + mailprivacy_mime_clear(signed_mime); + mailmime_free(signed_mime); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + mailmime_content_free(signed_mime->mm_content_type); + signed_mime->mm_content_type = content_type; + + /* place original MIME fields */ + + if (mime->mm_mime_fields != NULL) { + struct mailmime_fields * mime_fields; + clistiter * cur; + + mime_fields = mailprivacy_mime_fields_dup(privacy, + mime->mm_mime_fields); + if (mime_fields == NULL) { + mailprivacy_mime_clear(signed_mime); + mailmime_free(signed_mime); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + for(cur = clist_begin(mime_fields->fld_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) { + mailmime_field_free(field); + clist_delete(mime_fields->fld_list, cur); + break; + } + } + clist_concat(signed_mime->mm_mime_fields->fld_list, + mime_fields->fld_list); + mailmime_fields_free(mime_fields); + } + + unlink(description_filename); + unlink(signed_filename); + unlink(original_filename); + + * result = signed_mime; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_signed: + unlink(signed_filename); + unlink_original: + unlink(original_filename); + err: + return res; +} + + +static int pgp_armor_encrypt(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char original_filename[PATH_MAX]; + FILE * original_f; + char encrypted_filename[PATH_MAX]; + char quoted_original_filename[PATH_MAX]; + int col; + struct mailmime * encrypted_mime; + int res; + int r; + char command[PATH_MAX]; + struct mailmime_content * content_type; + struct mailmime * root; + struct mailimf_fields * fields; + char recipient[PATH_MAX]; + int encrypt_ok; + char description_filename[PATH_MAX]; + + if (mime->mm_type != MAILMIME_SINGLE) { + res = MAIL_ERROR_INVAL; + goto err; + } + + if (mime->mm_data.mm_single == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + root = mime; + while (root->mm_parent != NULL) + root = root->mm_parent; + + fields = NULL; + if (root->mm_type == MAILMIME_MESSAGE) + fields = root->mm_data.mm_message.mm_fields; + + /* recipient */ + + collect_recipient(recipient, sizeof(recipient), fields); + + /* get part to encrypt */ + + original_f = mailprivacy_get_tmp_file(privacy, original_filename, + sizeof(original_filename)); + if (original_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_data_write(original_f, &col, mime->mm_data.mm_single, 1); + if (r != MAILIMF_NO_ERROR) { + fclose(original_f); + res = MAIL_ERROR_FILE; + goto unlink_original; + } + fclose(original_f); + + r = mailprivacy_get_tmp_filename(privacy, encrypted_filename, + sizeof(encrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_original; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_encrypted; + } + + r = mail_quote_filename(quoted_original_filename, + sizeof(quoted_original_filename), original_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), "gpg %s --batch --yes -e --armor '%s'", + recipient, quoted_original_filename); + + encrypt_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + encrypted_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + encrypt_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + encrypt_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (!encrypt_ok) { + res = MAIL_ERROR_COMMAND; + goto unlink_description; + } + + /* building the encrypted part */ + + encrypted_mime = mailprivacy_new_file_part(privacy, + encrypted_filename, + "application/octet-stream", + MAILMIME_MECHANISM_8BIT); + if (encrypted_mime == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* place original content type */ + + content_type = mailmime_content_dup(mime->mm_content_type); + if (content_type == NULL) { + mailprivacy_mime_clear(encrypted_mime); + mailmime_free(encrypted_mime); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + mailmime_content_free(encrypted_mime->mm_content_type); + encrypted_mime->mm_content_type = content_type; + + /* place original MIME fields */ + + if (mime->mm_mime_fields != NULL) { + struct mailmime_fields * mime_fields; + clistiter * cur; + + mime_fields = mailprivacy_mime_fields_dup(privacy, mime->mm_mime_fields); + if (mime_fields == NULL) { + mailprivacy_mime_clear(encrypted_mime); + mailmime_free(encrypted_mime); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + for(cur = clist_begin(mime_fields->fld_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) { + mailmime_field_free(field); + clist_delete(mime_fields->fld_list, cur); + break; + } + } + clist_concat(encrypted_mime->mm_mime_fields->fld_list, + mime_fields->fld_list); + mailmime_fields_free(mime_fields); + } + + unlink(description_filename); + unlink(encrypted_filename); + unlink(original_filename); + + * result = encrypted_mime; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_encrypted: + unlink(encrypted_filename); + unlink_original: + unlink(original_filename); + err: + return res; +} + + +static int pgp_armor_sign_encrypt(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char default_key[PATH_MAX]; + char original_filename[PATH_MAX]; + FILE * original_f; + char encrypted_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char quoted_original_filename[PATH_MAX]; + int col; + struct mailmime * encrypted_mime; + int res; + int r; + char command[PATH_MAX]; + struct mailmime_content * content_type; + struct mailmime * root; + struct mailimf_fields * fields; + char recipient[PATH_MAX]; + char * email; + int encrypt_ok; + + if (mime->mm_type != MAILMIME_SINGLE) { + res = MAIL_ERROR_INVAL; + goto err; + } + + if (mime->mm_data.mm_single == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + /* get signing key */ + + * default_key = '\0'; + email = get_first_from_addr(mime); + if (email != NULL) + snprintf(default_key, sizeof(default_key), + "--default-key %s", email); + + root = mime; + while (root->mm_parent != NULL) + root = root->mm_parent; + + fields = NULL; + if (root->mm_type == MAILMIME_MESSAGE) + fields = root->mm_data.mm_message.mm_fields; + + /* recipient */ + + collect_recipient(recipient, sizeof(recipient), fields); + + /* get part to encrypt */ + + original_f = mailprivacy_get_tmp_file(privacy, + original_filename, + sizeof(original_filename)); + if (original_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_data_write(original_f, &col, mime->mm_data.mm_single, 1); + if (r != MAILIMF_NO_ERROR) { + fclose(original_f); + res = MAIL_ERROR_FILE; + goto unlink_original; + } + fclose(original_f); + + r = mailprivacy_get_tmp_filename(privacy, encrypted_filename, + sizeof(encrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FILE; + goto unlink_original; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_encrypted; + } + + r = mail_quote_filename(quoted_original_filename, + sizeof(quoted_original_filename), original_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), + "gpg --passphrase-fd=0 %s --batch --yes --digest-algo sha1 " + "%s -e -s -a '%s'", + recipient, default_key, quoted_original_filename); + + encrypt_ok = 0; + r = gpg_command_passphrase(privacy, msg, command, NULL, + encrypted_filename, description_filename); + switch (r) { + case NO_ERROR_PGP: + encrypt_ok = 1; + break; + case ERROR_PGP_NOPASSPHRASE: + case ERROR_PGP_CHECK: + encrypt_ok = 0; + break; + case ERROR_PGP_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_PGP_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (!encrypt_ok) { + res = MAIL_ERROR_COMMAND; + goto unlink_description; + } + + /* building the encrypted part */ + + encrypted_mime = mailprivacy_new_file_part(privacy, + encrypted_filename, + "application/octet-stream", + MAILMIME_MECHANISM_8BIT); + if (encrypted_mime == NULL) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* place original content type */ + + content_type = mailmime_content_dup(mime->mm_content_type); + if (content_type == NULL) { + mailprivacy_mime_clear(encrypted_mime); + mailmime_free(encrypted_mime); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + mailmime_content_free(encrypted_mime->mm_content_type); + encrypted_mime->mm_content_type = content_type; + + /* place original MIME fields */ + + if (mime->mm_mime_fields != NULL) { + struct mailmime_fields * mime_fields; + clistiter * cur; + + mime_fields = mailprivacy_mime_fields_dup(privacy, mime->mm_mime_fields); + if (mime_fields == NULL) { + mailprivacy_mime_clear(encrypted_mime); + mailmime_free(encrypted_mime); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + for(cur = clist_begin(mime_fields->fld_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) { + mailmime_field_free(field); + clist_delete(mime_fields->fld_list, cur); + break; + } + } + clist_concat(encrypted_mime->mm_mime_fields->fld_list, + mime_fields->fld_list); + mailmime_fields_free(mime_fields); + } + + unlink(description_filename); + unlink(encrypted_filename); + unlink(original_filename); + + * result = encrypted_mime; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_encrypted: + unlink(encrypted_filename); + unlink_original: + unlink(original_filename); + err: + return res; +} + +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L +static struct mailprivacy_encryption pgp_encryption_tab[] = { + /* PGP signed part */ + { + /* name */ "signed", + /* description */ "PGP signed part", + /* encrypt */ pgp_sign_mime, + }, + + /* pgp encrypted part */ + + { + /* name */ "encrypted", + /* description */ "PGP encrypted part", + /* encrypt */ pgp_encrypt_mime, + }, + + /* PGP signed & encrypted part */ + + { + /* name */ "signed-encrypted", + /* description */ "PGP signed & encrypted part", + /* encrypt */ pgp_sign_encrypt_mime, + }, + + /* PGP clear signed part */ + + { + /* name */ "clear-signed", + /* description */ "PGP clear signed part", + /* encrypt */ pgp_clear_sign, + }, + + /* PGP armor encrypted part */ + + { + /* name */ "encrypted-armor", + /* description */ "PGP ASCII armor encrypted part", + /* encrypt */ pgp_armor_encrypt, + }, + + /* PGP armor signed & encrypted part */ + + { + /* name */ "signed-encrypted-armor", + /* description */ "PGP ASCII armor signed & encrypted part", + /* encrypt */ pgp_armor_sign_encrypt, + }, +}; +#else +static struct mailprivacy_encryption pgp_encryption_tab[] = { + /* PGP signed part */ + { + .name = "signed", + .description = "PGP signed part", + .encrypt = pgp_sign_mime, + }, + + /* pgp encrypted part */ + + { + .name = "encrypted", + .description = "PGP encrypted part", + .encrypt = pgp_encrypt_mime, + }, + + /* PGP signed & encrypted part */ + + { + .name = "signed-encrypted", + .description = "PGP signed & encrypted part", + .encrypt = pgp_sign_encrypt_mime, + }, + + /* PGP clear signed part */ + + { + .name = "clear-signed", + .description = "PGP clear signed part", + .encrypt = pgp_clear_sign, + }, + + /* PGP armor encrypted part */ + + { + .name = "encrypted-armor", + .description = "PGP ASCII armor encrypted part", + .encrypt = pgp_armor_encrypt, + }, + + /* PGP armor signed & encrypted part */ + + { + .name = "signed-encrypted-armor", + .description = "PGP ASCII armor signed & encrypted part", + .encrypt = pgp_armor_sign_encrypt, + }, +}; +#endif + +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L +static struct mailprivacy_protocol pgp_protocol = { + /* name */ "pgp", + /* description */ "OpenPGP", + + /* is_encrypted */ pgp_test_encrypted, + /* decrypt */ pgp_handler, + + /* encryption_count */ + (sizeof(pgp_encryption_tab) / sizeof(pgp_encryption_tab[0])), + + /* encryption_tab */ pgp_encryption_tab, +}; +#else +static struct mailprivacy_protocol pgp_protocol = { + .name = "pgp", + .description = "OpenPGP", + + .is_encrypted = pgp_test_encrypted, + .decrypt = pgp_handler, + + .encryption_count = + (sizeof(pgp_encryption_tab) / sizeof(pgp_encryption_tab[0])), + + .encryption_tab = pgp_encryption_tab, +}; +#endif + +int mailprivacy_gnupg_init(struct mailprivacy * privacy) +{ + return mailprivacy_register(privacy, &pgp_protocol); +} + +void mailprivacy_gnupg_done(struct mailprivacy * privacy) +{ + mailprivacy_unregister(privacy, &pgp_protocol); +} + + +#ifdef LIBETPAN_REENTRANT +static pthread_mutex_t encryption_id_hash_lock = PTHREAD_MUTEX_INITIALIZER; +#endif +static chash * encryption_id_hash = NULL; + +static clist * get_list(struct mailprivacy * privacy, mailmessage * msg) +{ + clist * encryption_id_list; + + encryption_id_list = NULL; + if (encryption_id_hash != NULL) { + chashdatum key; + chashdatum value; + int r; + + key.data = &msg; + key.len = sizeof(msg); + r = chash_get(encryption_id_hash, &key, &value); + if (r == 0) { + encryption_id_list = value.data; + } + } + + return encryption_id_list; +} + +void mailprivacy_gnupg_encryption_id_list_clear(struct mailprivacy * privacy, + mailmessage * msg) +{ + clist * encryption_id_list; + clistiter * iter; + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&encryption_id_hash_lock); +#endif + encryption_id_list = get_list(privacy, msg); + if (encryption_id_list != NULL) { + chashdatum key; + + for(iter = clist_begin(encryption_id_list) ; + iter != NULL ; iter = clist_next(iter)) { + char * str; + + str = clist_content(iter); + free(str); + } + clist_free(encryption_id_list); + + key.data = &msg; + key.len = sizeof(msg); + chash_delete(encryption_id_hash, &key, NULL); + + if (chash_count(encryption_id_hash) == 0) { + chash_free(encryption_id_hash); + encryption_id_hash = NULL; + } + } +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&encryption_id_hash_lock); +#endif +} + +clist * mailprivacy_gnupg_encryption_id_list(struct mailprivacy * privacy, + mailmessage * msg) +{ + clist * encryption_id_list; + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&encryption_id_hash_lock); +#endif + encryption_id_list = get_list(privacy, msg); +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&encryption_id_hash_lock); +#endif + + return encryption_id_list; +} + +static int mailprivacy_gnupg_add_encryption_id(struct mailprivacy * privacy, + mailmessage * msg, char * encryption_id) +{ + clist * encryption_id_list; + int r; + int res; + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&encryption_id_hash_lock); +#endif + + res = -1; + + encryption_id_list = get_list(privacy, msg); + if (encryption_id_list == NULL) { + if (encryption_id_hash == NULL) + encryption_id_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + + if (encryption_id_hash != NULL) { + encryption_id_list = clist_new(); + if (encryption_id_list != NULL) { + chashdatum key; + chashdatum value; + + key.data = &msg; + key.len = sizeof(msg); + value.data = encryption_id_list; + value.len = 0; + r = chash_set(encryption_id_hash, &key, &value, NULL); + if (r < 0) + clist_free(encryption_id_list); + } + } + } + + encryption_id_list = get_list(privacy, msg); + if (encryption_id_list != NULL) { + char * str; + + str = strdup(encryption_id); + if (str != NULL) { + r = clist_append(encryption_id_list, str); + if (r < 0) { + free(str); + } + else { + res = 0; + } + } + } + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&encryption_id_hash_lock); +#endif + + return res; +} + +#define MAX_EMAIL_SIZE 1024 + +static chash * passphrase_hash = NULL; + +int mailprivacy_gnupg_set_encryption_id(struct mailprivacy * privacy, + char * user_id, char * passphrase) +{ + chashdatum key; + chashdatum value; + int r; + char buf[MAX_EMAIL_SIZE]; + char * n; + + strncpy(buf, user_id, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + for(n = buf ; * n != '\0' ; n ++) + * n = toupper((unsigned char) * n); + + if (passphrase_hash == NULL) { + passphrase_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (passphrase_hash == NULL) + return MAIL_ERROR_MEMORY; + } + + key.data = buf; + key.len = strlen(buf) + 1; + value.data = passphrase; + value.len = strlen(passphrase) + 1; + + r = chash_set(passphrase_hash, &key, &value, NULL); + if (r < 0) { + return MAIL_ERROR_MEMORY; + } + + return MAIL_NO_ERROR; +} + +static char * get_passphrase(struct mailprivacy * privacy, + char * user_id) +{ + chashdatum key; + chashdatum value; + int r; + char * passphrase; + char buf[MAX_EMAIL_SIZE]; + char * n; + + strncpy(buf, user_id, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + for(n = buf ; * n != '\0' ; n ++) + * n = toupper((unsigned char) * n); + + if (passphrase_hash == NULL) + return NULL; + + key.data = buf; + key.len = strlen(buf) + 1; + + r = chash_get(passphrase_hash, &key, &value); + if (r < 0) + return NULL; + + passphrase = strdup(value.data); + + return passphrase; +} Added: freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_gnupg.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_gnupg.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,55 @@ +/* + * etPan! -- a mail user agent + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_gnupg.h,v 1.4 2005/11/21 16:17:57 hoa Exp $ + */ + +#ifndef MAIL_PRIVACY_GNUPG_H + +#define MAIL_PRIVACY_GNUPG_H + +#include <libetpan/mailprivacy_types.h> + +int mailprivacy_gnupg_init(struct mailprivacy * privacy); + +void mailprivacy_gnupg_done(struct mailprivacy * privacy); + +clist * mailprivacy_gnupg_encryption_id_list(struct mailprivacy * privacy, + mailmessage * msg); + +void mailprivacy_gnupg_encryption_id_list_clear(struct mailprivacy * privacy, + mailmessage * msg); + +int mailprivacy_gnupg_set_encryption_id(struct mailprivacy * privacy, + char * user_id, char * passphrase); + +#endif Added: freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_smime.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_smime.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,2001 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_smime.c,v 1.15 2006/08/29 22:27:35 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailprivacy_smime.h" +#include <string.h> +#include <pthread.h> +#include <sys/wait.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> +#include "mailprivacy_tools.h" +#include "mailprivacy.h" +#include <stdlib.h> +#include <dirent.h> +#include <stdio.h> +#include <ctype.h> +#include <libetpan/libetpan-config.h> + +/* + global variable + + TODO : instance of privacy drivers +*/ + +static int smime_command_passphrase(struct mailprivacy * privacy, + struct mailmessage * msg, + char * command, + char * passphrase, + char * stdoutfile, char * stderrfile); +static char * get_passphrase(struct mailprivacy * privacy, + char * user_id); +static int mailprivacy_smime_add_encryption_id(struct mailprivacy * privacy, + mailmessage * msg, char * encryption_id); + +static char cert_dir[PATH_MAX] = ""; +static chash * certificates = NULL; +static chash * private_keys = NULL; +static char CAcert_dir[PATH_MAX] = ""; +static char * CAfile = NULL; +static int CA_check = 1; +static int store_cert = 0; +static char private_keys_dir[PATH_MAX] = ""; + +static char * get_cert_file(char * email); + +static char * get_private_key_file(char * email); + + +static int smime_is_signed(struct mailmime * mime) +{ + if (mime->mm_content_type != NULL) { + if ((strcasecmp(mime->mm_content_type->ct_subtype, "x-pkcs7-mime") == 0) || + (strcasecmp(mime->mm_content_type->ct_subtype, "pkcs7-mime") == 0)) { + clistiter * cur; + + for(cur = clist_begin(mime->mm_content_type->ct_parameters) ; + cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = cur->data; + + if ((strcasecmp(param->pa_name, "smime-type") == 0) && + (strcasecmp(param->pa_value, "signed-data") == 0)) + return 1; + } + + return 0; + } + else { + clistiter * cur; + + for(cur = clist_begin(mime->mm_content_type->ct_parameters) ; + cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = cur->data; + + if ((strcasecmp(param->pa_name, "protocol") == 0) && + ((strcasecmp(param->pa_value, + "application/x-pkcs7-signature") == 0) || + (strcasecmp(param->pa_value, + "application/pkcs7-signature") == 0))) + return 1; + } + } + } + + return 0; +} + +static int smime_is_encrypted(struct mailmime * mime) +{ + if (mime->mm_content_type != NULL) { + if ((strcasecmp(mime->mm_content_type->ct_subtype, "x-pkcs7-mime") == 0) || + (strcasecmp(mime->mm_content_type->ct_subtype, "pkcs7-mime") == 0)) { + clistiter * cur; + + for(cur = clist_begin(mime->mm_content_type->ct_parameters) ; + cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = cur->data; + + if ((strcasecmp(param->pa_name, "smime-type") == 0) && + (strcasecmp(param->pa_value, "signed-data") == 0)) + return 0; + } + + return 1; + } + } + + return 0; +} + + +enum { + NO_ERROR_SMIME = 0, + ERROR_SMIME_CHECK, + ERROR_SMIME_COMMAND, + ERROR_SMIME_FILE, + ERROR_SMIME_NOPASSPHRASE +}; + +#define BUF_SIZE 1024 + +static char * get_first_from_addr(struct mailmime * mime) +{ + clistiter * cur; + struct mailimf_single_fields single_fields; + struct mailimf_fields * fields; + struct mailimf_mailbox * mb; + + while (mime->mm_parent != NULL) + mime = mime->mm_parent; + + if (mime->mm_type != MAILMIME_MESSAGE) + return NULL; + + fields = mime->mm_data.mm_message.mm_fields; + if (fields == NULL) + return NULL; + + mailimf_single_fields_init(&single_fields, fields); + + if (single_fields.fld_from == NULL) + return NULL; + + cur = clist_begin(single_fields.fld_from->frm_mb_list->mb_list); + if (cur == NULL) + return NULL; + + mb = clist_content(cur); + + return mb->mb_addr_spec; +} + +#define SMIME_DECRYPT_DESCRIPTION "S/MIME encrypted part\r\n" +#define SMIME_DECRYPT_FAILED "S/MIME decryption FAILED\r\n" +#define SMIME_DECRYPT_SUCCESS "S/MIME decryption success\r\n" + +/* passphrase will be needed */ + +static int smime_decrypt(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char smime_filename[PATH_MAX]; + char quoted_smime_filename[PATH_MAX]; + char description_filename[PATH_MAX]; + char decrypted_filename[PATH_MAX]; + char command[PATH_MAX]; + struct mailmime * description_mime; + struct mailmime * decrypted_mime; + int r; + int res; + int sign_ok; + struct mailmime * multipart; + char * smime_cert; + char * smime_key; + char quoted_smime_cert[PATH_MAX]; + char quoted_smime_key[PATH_MAX]; + char * email; + chashiter * iter; + + /* fetch the whole multipart and write it to a file */ + + r = mailprivacy_fetch_mime_body_to_file(privacy, + smime_filename, sizeof(smime_filename), + msg, mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + /* we are in a safe directory */ + + r = mailprivacy_get_tmp_filename(privacy, decrypted_filename, + sizeof(decrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FILE; + goto unlink_smime; + } + + /* description */ + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FILE; + goto unlink_decrypted; + } + + sign_ok = 0; + for(iter = chash_begin(private_keys) ; iter != NULL ; + iter = chash_next(private_keys, iter)) { + chashdatum key; + char email_buf[BUF_SIZE]; + + chash_key(iter, &key); + + if (key.len >= sizeof(email_buf)) + continue; + + strncpy(email_buf, key.data, key.len); + email_buf[key.len] = '\0'; + email = email_buf; + + /* get encryption key */ + + smime_key = get_private_key_file(email); + smime_cert = get_cert_file(email); + if ((smime_cert == NULL) || (smime_key == NULL)) { + res = MAIL_ERROR_INVAL; + goto unlink_description; + } + + r = mail_quote_filename(quoted_smime_cert, sizeof(quoted_smime_cert), + smime_cert); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = mail_quote_filename(quoted_smime_key, sizeof(quoted_smime_key), + smime_key); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* run the command */ + + r = mail_quote_filename(quoted_smime_filename, + sizeof(quoted_smime_filename), smime_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + sign_ok = 0; + snprintf(command, sizeof(command), + "openssl smime -decrypt -passin fd:0 -in '%s' -inkey '%s' -recip '%s'", + quoted_smime_filename, quoted_smime_key, quoted_smime_cert); + + unlink(description_filename); + r = smime_command_passphrase(privacy, msg, command, + email, decrypted_filename, description_filename); + switch (r) { + case NO_ERROR_SMIME: + sign_ok = 1; + break; + case ERROR_SMIME_CHECK: + case ERROR_SMIME_NOPASSPHRASE: + sign_ok = 0; + break; + case ERROR_SMIME_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_SMIME_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + if (sign_ok) { + break; + } + } + + if (!sign_ok) { + if (chash_count(private_keys) == 0) { + FILE * description_f; + + description_f = mailprivacy_get_tmp_file(privacy, description_filename, + sizeof(description_filename)); + if (description_f == NULL) { + res = MAIL_ERROR_FILE; + goto unlink_decrypted; + } + fprintf(description_f, SMIME_DECRYPT_FAILED); + fclose(description_f); + } + } + else { + mailprivacy_smime_encryption_id_list_clear(privacy, msg); + } + + /* building multipart */ + + r = mailmime_new_with_content("multipart/x-decrypted", NULL, &multipart); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the description part */ + + description_mime = mailprivacy_new_file_part(privacy, + description_filename, + "text/plain", MAILMIME_MECHANISM_8BIT); + if (description_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* adds the description part */ + + r = mailmime_smart_add_part(multipart, description_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(description_mime); + mailmime_free(description_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the decrypted part */ + + r = mailprivacy_get_part_from_file(privacy, 1, 0, + decrypted_filename, &decrypted_mime); + if (r == MAIL_NO_ERROR) { + /* adds the decrypted part */ + + r = mailmime_smart_add_part(multipart, decrypted_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(decrypted_mime); + mailmime_free(decrypted_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + } + + unlink(description_filename); + unlink(decrypted_filename); + unlink(smime_filename); + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_decrypted: + unlink(decrypted_filename); + unlink_smime: + unlink(smime_filename); + err: + return res; +} + + +static int get_cert_from_sig(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime); + +#define SMIME_VERIFY_DESCRIPTION "S/MIME verify signed message\r\n" +#define SMIME_VERIFY_FAILED "S/MIME verification FAILED\r\n" +#define SMIME_VERIFY_SUCCESS "S/MIME verification success\r\n" + +static int +smime_verify(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char smime_filename[PATH_MAX]; + char quoted_smime_filename[PATH_MAX]; + int res; + int r; + char command[PATH_MAX]; + int sign_ok; + struct mailmime * description_mime; + char description_filename[PATH_MAX]; + struct mailmime * multipart; + char stripped_filename[PATH_MAX]; + struct mailmime * stripped_mime; + char check_CA[PATH_MAX]; + char quoted_CAfile[PATH_MAX]; + char noverify[PATH_MAX]; + + if (store_cert) + get_cert_from_sig(privacy, msg, mime); + + * check_CA = '\0'; + if (CAfile != NULL) { + r = mail_quote_filename(quoted_CAfile, sizeof(quoted_CAfile), CAfile); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto err; + } + + snprintf(check_CA, sizeof(check_CA), "-CAfile '%s'", quoted_CAfile); + } + + * noverify = '\0'; + if (!CA_check) { + snprintf(noverify, sizeof(noverify), "-noverify"); + } + + /* fetch the whole multipart and write it to a file */ + + r = mailprivacy_fetch_mime_body_to_file(privacy, + smime_filename, sizeof(smime_filename), + msg, mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = mailprivacy_get_tmp_filename(privacy,stripped_filename, + sizeof(stripped_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_smime; + } + + /* description */ + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_stripped; + } + + /* run the command */ + + r = mail_quote_filename(quoted_smime_filename, + sizeof(quoted_smime_filename), smime_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + sign_ok = 0; + snprintf(command, sizeof(command), "openssl smime -verify -in '%s' %s %s", + quoted_smime_filename, check_CA, noverify); + + r = smime_command_passphrase(privacy, msg, command, + NULL, stripped_filename, description_filename); + switch (r) { + case NO_ERROR_SMIME: + sign_ok = 1; + break; + case ERROR_SMIME_NOPASSPHRASE: + case ERROR_SMIME_CHECK: + sign_ok = 0; + break; + case ERROR_SMIME_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_SMIME_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + /* building multipart */ + + r = mailmime_new_with_content("multipart/x-verified", NULL, &multipart); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* building the description part */ + + description_mime = mailprivacy_new_file_part(privacy, + description_filename, + "text/plain", MAILMIME_MECHANISM_8BIT); + if (description_mime == NULL) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* adds the description part */ + + r = mailmime_smart_add_part(multipart, description_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(description_mime); + mailmime_free(description_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + /* insert the signed part */ + if (!sign_ok) { + if (mime->mm_type == MAILMIME_MULTIPLE) { + clistiter * child_iter; + struct mailmime * child; + + child_iter = clist_begin(mime->mm_data.mm_multipart.mm_mp_list); + child = clist_content(child_iter); + + r = mailprivacy_fetch_mime_body_to_file(privacy, + stripped_filename, sizeof(stripped_filename), + msg, child); + } + } + + r = mailprivacy_get_part_from_file(privacy, 1, 0, + stripped_filename, &stripped_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = r; + goto unlink_description; + } + + r = mailmime_smart_add_part(multipart, stripped_mime); + if (r != MAIL_NO_ERROR) { + mailprivacy_mime_clear(stripped_mime); + mailmime_free(stripped_mime); + mailprivacy_mime_clear(multipart); + mailmime_free(multipart); + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + unlink(description_filename); + unlink(stripped_filename); + /* unlink(smime_filename); */ + + * result = multipart; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_stripped: + unlink(stripped_filename); + unlink_smime: + unlink(smime_filename); + err: + return res; +} + +static int smime_test_encrypted(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime) +{ + switch (mime->mm_type) { + case MAILMIME_MULTIPLE: + return smime_is_signed(mime); + + case MAILMIME_SINGLE: + return smime_is_encrypted(mime) || smime_is_signed(mime); + } + + return 0; +} + +static int smime_handler(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + int r; + struct mailmime * alternative_mime; + + alternative_mime = NULL; + switch (mime->mm_type) { + case MAILMIME_MULTIPLE: + r = MAIL_ERROR_INVAL; + if (smime_is_signed(mime)) + r = smime_verify(privacy, msg, mime, &alternative_mime); + + if (r != MAIL_NO_ERROR) + return r; + + * result = alternative_mime; + + return MAIL_NO_ERROR; + + case MAILMIME_SINGLE: + r = MAIL_ERROR_INVAL; + if (smime_is_encrypted(mime)) + r = smime_decrypt(privacy, msg, mime, &alternative_mime); + else if (smime_is_signed(mime)) + r = smime_verify(privacy, msg, mime, &alternative_mime); + + if (r != MAIL_NO_ERROR) + return r; + + * result = alternative_mime; + + return MAIL_NO_ERROR; + } + + return MAIL_ERROR_INVAL; +} + + + + +static void strip_mime_headers(struct mailmime * mime) +{ + struct mailmime_fields * fields; + clistiter * cur; + + fields = mime->mm_mime_fields; + + if (fields == NULL) + return; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + + if (field->fld_type == MAILMIME_FIELD_VERSION) { + mailmime_field_free(field); + clist_delete(fields->fld_list, cur); + break; + } + } +} + +/* passphrase is needed */ + +static int smime_sign(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char signed_filename[PATH_MAX]; + FILE * signed_f; + int res; + int r; + int col; + char description_filename[PATH_MAX]; + char signature_filename[PATH_MAX]; + char command[PATH_MAX]; + char quoted_signed_filename[PATH_MAX]; + struct mailmime * signed_mime; + char * smime_cert; + char * smime_key; + char quoted_smime_cert[PATH_MAX]; + char quoted_smime_key[PATH_MAX]; + char * email; + + /* get signing key */ + + email = get_first_from_addr(mime); + if (email == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + smime_key = get_private_key_file(email); + smime_cert = get_cert_file(email); + if ((smime_cert == NULL) || (smime_key == NULL)) { + res = MAIL_ERROR_INVAL; + goto err; + } + + /* part to sign */ + + /* encode quoted printable all text parts */ + + mailprivacy_prepare_mime(mime); + + signed_f = mailprivacy_get_tmp_file(privacy, + signed_filename, sizeof(signed_filename)); + if (signed_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_write(signed_f, &col, mime); + if (r != MAILIMF_NO_ERROR) { + fclose(signed_f); + res = MAIL_ERROR_FILE; + goto unlink_signed; + } + + fclose(signed_f); + + /* prepare destination file for signature */ + + r = mailprivacy_get_tmp_filename(privacy, signature_filename, + sizeof(signature_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_signed; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_signature; + } + + r = mail_quote_filename(quoted_signed_filename, + sizeof(quoted_signed_filename), signed_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = mail_quote_filename(quoted_smime_key, + sizeof(quoted_smime_key), smime_key); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + r = mail_quote_filename(quoted_smime_cert, + sizeof(quoted_smime_cert), smime_cert); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), + "openssl smime -sign -passin fd:0 -in '%s' -signer '%s' -inkey '%s'", + quoted_signed_filename, + quoted_smime_cert, quoted_smime_key); + + r = smime_command_passphrase(privacy, msg, command, + email, signature_filename, description_filename); + switch (r) { + case NO_ERROR_SMIME: + break; + case ERROR_SMIME_NOPASSPHRASE: + case ERROR_SMIME_CHECK: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + break; + case ERROR_SMIME_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + case ERROR_SMIME_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + /* signature part */ + + r = mailprivacy_get_part_from_file(privacy, 0, 0, + signature_filename, &signed_mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_description; + } + strip_mime_headers(signed_mime); + + unlink(description_filename); + /* unlink(signature_filename); */ + /* unlink(signed_filename); */ + + * result = signed_mime; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_signature: + unlink(signature_filename); + unlink_signed: + unlink(signed_filename); + err: + return res; +} + + +/* ********************************************************************* */ +/* find S/MIME recipient */ + +static int recipient_add_mb(char * recipient, size_t * len, + struct mailimf_mailbox * mb) +{ + char * filename; + char quoted_filename[PATH_MAX]; + size_t buflen; + int r; + + if (mb->mb_addr_spec == NULL) + return MAIL_NO_ERROR; + + filename = get_cert_file(mb->mb_addr_spec); + if (filename == NULL) + return MAIL_ERROR_INVAL; + + r = mail_quote_filename(quoted_filename, sizeof(quoted_filename), + filename); + if (r < 0) + return MAIL_ERROR_MEMORY; + + buflen = strlen(quoted_filename + 1); + if (buflen >= * len) + return MAIL_ERROR_MEMORY; + + strncat(recipient, "\'", * len); + (* len) --; + strncat(recipient, quoted_filename, * len); + (* len) -= buflen; + strncat(recipient, "\'", * len); + (* len) --; + strncat(recipient, " ", * len); + (* len) --; + + return MAIL_NO_ERROR; +} + +static int recipient_add_mb_list(char * recipient, size_t * len, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + r = recipient_add_mb(recipient, len, mb); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + +static int recipient_add_group(char * recipient, size_t * len, + struct mailimf_group * group) +{ + return recipient_add_mb_list(recipient, len, group->grp_mb_list); +} + +static int recipient_add_addr(char * recipient, size_t * len, + struct mailimf_address * addr) +{ + int r; + + switch (addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = recipient_add_mb(recipient, len, addr->ad_data.ad_mailbox); + break; + case MAILIMF_ADDRESS_GROUP: + r = recipient_add_group(recipient, len, addr->ad_data.ad_group); + break; + default: + r = MAIL_ERROR_INVAL; + } + + return r; +} + +static int recipient_add_addr_list(char * recipient, size_t * len, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + r = recipient_add_addr(recipient, len, addr); + if (r != MAIL_NO_ERROR) + return r; + } + + return MAIL_NO_ERROR; +} + +static int collect_smime_cert(char * recipient, size_t size, + struct mailimf_fields * fields) +{ + struct mailimf_single_fields single_fields; + int r; + size_t remaining; + int res; + + * recipient = '\0'; + remaining = size; + + if (fields != NULL) + mailimf_single_fields_init(&single_fields, fields); + + if (single_fields.fld_to != NULL) { + r = recipient_add_addr_list(recipient, &remaining, + single_fields.fld_to->to_addr_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + if (single_fields.fld_cc != NULL) { + r = recipient_add_addr_list(recipient, &remaining, + single_fields.fld_cc->cc_addr_list); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + if (single_fields.fld_bcc != NULL) { + if (single_fields.fld_bcc->bcc_addr_list != NULL) { + r = recipient_add_addr_list(recipient, &remaining, + single_fields.fld_bcc->bcc_addr_list); + if (r < 0) { + res = r; + goto err; + } + } + } + + return MAIL_NO_ERROR; + + err: + return res; +} + + + +static int smime_encrypt(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + char encrypted_filename[PATH_MAX]; + int res; + int r; + int col; + char description_filename[PATH_MAX]; + char decrypted_filename[PATH_MAX]; + FILE * decrypted_f; + char command[PATH_MAX]; + char quoted_decrypted_filename[PATH_MAX]; + struct mailmime * encrypted_mime; + struct mailmime * root; + struct mailimf_fields * fields; + char recipient[PATH_MAX]; + + root = mime; + while (root->mm_parent != NULL) + root = root->mm_parent; + + fields = NULL; + if (root->mm_type == MAILMIME_MESSAGE) + fields = root->mm_data.mm_message.mm_fields; + + /* recipient */ + r = collect_smime_cert(recipient, sizeof(recipient), fields); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + /* part to encrypt */ + + /* encode quoted printable all text parts */ + + mailprivacy_prepare_mime(mime); + + decrypted_f = mailprivacy_get_tmp_file(privacy, + decrypted_filename, + sizeof(decrypted_filename)); + if (decrypted_f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + col = 0; + r = mailmime_write(decrypted_f, &col, mime); + if (r != MAILIMF_NO_ERROR) { + fclose(decrypted_f); + res = MAIL_ERROR_FILE; + goto unlink_decrypted; + } + + fclose(decrypted_f); + + /* prepare destination file for encryption */ + + r = mailprivacy_get_tmp_filename(privacy, encrypted_filename, + sizeof(encrypted_filename)); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FILE; + goto unlink_decrypted; + } + + r = mailprivacy_get_tmp_filename(privacy, description_filename, + sizeof(description_filename)); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FILE; + goto unlink_encrypted; + } + + r = mail_quote_filename(quoted_decrypted_filename, + sizeof(quoted_decrypted_filename), decrypted_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_description; + } + + snprintf(command, sizeof(command), "openssl smime -encrypt -in '%s' %s", + quoted_decrypted_filename, recipient); + + r = smime_command_passphrase(privacy, msg, command, + NULL, encrypted_filename, description_filename); + switch (r) { + case NO_ERROR_SMIME: + break; + case ERROR_SMIME_NOPASSPHRASE: + case ERROR_SMIME_CHECK: + res = MAIL_ERROR_COMMAND; + goto unlink_description; + break; + case ERROR_SMIME_COMMAND: + res = MAIL_ERROR_COMMAND; + goto unlink_encrypted; + case ERROR_SMIME_FILE: + res = MAIL_ERROR_FILE; + goto unlink_description; + } + + /* encrypted part */ + + r = mailprivacy_get_part_from_file(privacy, 0, 0, + encrypted_filename, &encrypted_mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto unlink_description; + } + strip_mime_headers(encrypted_mime); + + unlink(description_filename); + unlink(encrypted_filename); + unlink(decrypted_filename); + + * result = encrypted_mime; + + return MAIL_NO_ERROR; + + unlink_description: + unlink(description_filename); + unlink_encrypted: + unlink(encrypted_filename); + unlink_decrypted: + unlink(decrypted_filename); + err: + return res; +} + + +/* passphrase will be needed */ + +static int smime_sign_encrypt(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime, struct mailmime ** result) +{ + struct mailmime * signed_part; + struct mailmime * encrypted; + int r; + int res; + + r = smime_sign(privacy, msg, mime, &signed_part); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + r = smime_encrypt(privacy, msg, signed_part, &encrypted); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_signed; + } + + * result = encrypted; + + return MAIL_NO_ERROR; + + free_signed: + mailprivacy_mime_clear(signed_part); + mailmime_free(signed_part); + err: + return res; +} + + +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L +static struct mailprivacy_encryption smime_encryption_tab[] = { + /* S/MIME signed part */ + { + /* name */ "signed", + /* description */ "S/MIME signed part", + /* encrypt */ smime_sign, + }, + + /* S/MIME encrypted part */ + + { + /* name */ "encrypted", + /* description */ "S/MIME encrypted part", + /* encrypt */ smime_encrypt, + }, + + /* S/MIME signed & encrypted part */ + + { + /* name */ "signed-encrypted", + /* description */ "S/MIME signed & encrypted part", + /* encrypt */ smime_sign_encrypt, + }, +}; +#else +static struct mailprivacy_encryption smime_encryption_tab[] = { + /* S/MIME signed part */ + { + .name = "signed", + .description = "S/MIME signed part", + .encrypt = smime_sign, + }, + + /* S/MIME encrypted part */ + + { + .name = "encrypted", + .description = "S/MIME encrypted part", + .encrypt = smime_encrypt, + }, + + /* S/MIME signed & encrypted part */ + + { + .name = "signed-encrypted", + .description = "S/MIME signed & encrypted part", + .encrypt = smime_sign_encrypt, + }, +}; +#endif + +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L +static struct mailprivacy_protocol smime_protocol = { + /* name */ "smime", + /* description */ "S/MIME", + + /* is_encrypted */ smime_test_encrypted, + /* decrypt */ smime_handler, + + /* encryption_count */ + (sizeof(smime_encryption_tab) / sizeof(smime_encryption_tab[0])), + + /* encryption_tab */ smime_encryption_tab, +}; +#else +static struct mailprivacy_protocol smime_protocol = { + .name = "smime", + .description = "S/MIME", + + .is_encrypted = smime_test_encrypted, + .decrypt = smime_handler, + + .encryption_count = + (sizeof(smime_encryption_tab) / sizeof(smime_encryption_tab[0])), + + .encryption_tab = smime_encryption_tab, +}; +#endif + +int mailprivacy_smime_init(struct mailprivacy * privacy) +{ + certificates = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (certificates == NULL) + goto err; + + private_keys = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (private_keys == NULL) + goto free_cert; + + CAcert_dir[0] = '\0'; + + return mailprivacy_register(privacy, &smime_protocol); + + free_cert: + chash_free(certificates); + err: + return MAIL_ERROR_MEMORY; +} + +void mailprivacy_smime_done(struct mailprivacy * privacy) +{ + mailprivacy_unregister(privacy, &smime_protocol); + chash_free(private_keys); + private_keys = NULL; + chash_free(certificates); + certificates = NULL; + if (CAfile != NULL) { + unlink(CAfile); + free(CAfile); + } + CAfile = NULL; + CAcert_dir[0] = '\0'; +} + + +static void strip_string(char * str) +{ + char * p; + size_t len; + + p = strchr(str, '\r'); + if (p != NULL) + * p = 0; + + p = strchr(str, '\n'); + if (p != NULL) + * p = 0; + + p = str; + while ((* p == ' ') || (* p == '\t')) { + p ++; + } + + len = strlen(p); + memmove(str, p, len); + str[len] = 0; + + if (len == 0) + return; + + p = str; + len = len - 1; + while ((p[len] == ' ') || (p[len] == '\t')) { + p[len] = '\0'; + + if (len == 0) + break; + + len --; + } +} + + + +#define MAX_EMAIL_SIZE 1024 + +static void set_file(chash * hash, char * email, char * filename) +{ + char * n; + char buf[MAX_EMAIL_SIZE]; + chashdatum key; + chashdatum data; + + strncpy(buf, email, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + for(n = buf ; * n != '\0' ; n ++) + * n = toupper((unsigned char) * n); + strip_string(buf); + + key.data = buf; + key.len = strlen(buf); + data.data = filename; + data.len = strlen(filename) + 1; + + chash_set(hash, &key, &data, NULL); +} + +static char * get_file(chash * hash, char * email) +{ + chashdatum key; + chashdatum data; + char buf[MAX_EMAIL_SIZE]; + char * n; + int r; + + strncpy(buf, email, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + for(n = buf ; * n != '\0' ; n ++) + * n = toupper((unsigned char) * n); + + strip_string(buf); + key.data = buf; + key.len = strlen(buf); + r = chash_get(hash, &key, &data); + if (r < 0) + return NULL; + + return data.data; +} + +#define CERTIFICATE_SUFFIX "-cert.pem" + +void mailprivacy_smime_set_cert_dir(struct mailprivacy * privacy, + char * directory) +{ + DIR * dir; + struct dirent * ent; + + chash_clear(certificates); + + if (directory == NULL) + return; + + if (* directory == '\0') + return; + + strncpy(cert_dir, directory, sizeof(cert_dir)); + cert_dir[sizeof(cert_dir) - 1] = '\0'; + + dir = opendir(directory); + if (dir == NULL) + return; + + while ((ent = readdir(dir)) != NULL) { +#if 0 + char quoted_filename[PATH_MAX]; + char filename[PATH_MAX]; + char command[PATH_MAX]; + char buf[MAX_EMAIL_SIZE]; + FILE * p; + int r; + + snprintf(filename, sizeof(filename), + "%s/%s", directory, ent->d_name); + + r = mail_quote_filename(quoted_filename, sizeof(quoted_filename), filename); + + snprintf(command, sizeof(command), + "openssl x509 -email -noout -in '%s' 2>/dev/null", quoted_filename); + + p = popen(command, "r"); + if (p == NULL) + continue; + + while (fgets(buf, sizeof(buf), p) != NULL) + set_file(certificates, buf, filename); + + pclose(p); +#endif + char filename[PATH_MAX]; + char email[PATH_MAX]; + char * p; + + snprintf(filename, sizeof(filename), + "%s/%s", directory, ent->d_name); + + strncpy(email, ent->d_name, sizeof(email)); + email[sizeof(email) - 1] = '\0'; + + p = strstr(email, CERTIFICATE_SUFFIX); + if (p == NULL) + continue; + + if (strlen(p) != sizeof(CERTIFICATE_SUFFIX) - 1) + continue; + + * p = 0; + + if (* email == '\0') + continue; + + set_file(certificates, email, filename); + } + closedir(dir); +} + +static char * get_cert_file(char * email) +{ + return get_file(certificates, email); +} + +static char * get_private_key_file(char * email) +{ + return get_file(private_keys, email); +} + +void mail_private_smime_clear_private_keys(struct mailprivacy * privacy) +{ + chash_clear(private_keys); +} + +#define MAX_BUF 1024 + +void mailprivacy_smime_set_CA_dir(struct mailprivacy * privacy, + char * directory) +{ + DIR * dir; + struct dirent * ent; + FILE * f_CA; + char CA_filename[PATH_MAX]; + + if (directory == NULL) + return; + + if (* directory == '\0') + return; + + /* make a temporary file that contains all the CAs */ + + if (CAfile != NULL) { + unlink(CAfile); + free(CAfile); + CAfile = NULL; + } + + f_CA = mailprivacy_get_tmp_file(privacy, CA_filename, sizeof(CA_filename)); + if (f_CA == NULL) + return; + + strncpy(CAcert_dir, directory, sizeof(CAcert_dir)); + CAcert_dir[sizeof(CAcert_dir) - 1] = '\0'; + + dir = opendir(directory); + if (dir == NULL) { + fclose(f_CA); + goto unlink_CA; + } + + while ((ent = readdir(dir)) != NULL) { + char filename[PATH_MAX]; + char buf[MAX_BUF]; + FILE * f; + + snprintf(filename, sizeof(filename), + "%s/%s", directory, ent->d_name); + + f = fopen(filename, "r"); + if (f == NULL) + continue; + + while (fgets(buf, sizeof(buf), f) != NULL) + fputs(buf, f_CA); + + fclose(f); + } + + closedir(dir); + + fclose(f_CA); + + CAfile = strdup(CA_filename); + if (CAfile == NULL) + goto unlink_CA; + + return; + + unlink_CA: + unlink(CA_filename); +} + +void mailprivacy_smime_set_CA_check(struct mailprivacy * privacy, + int enabled) +{ + CA_check = enabled; +} + +void mailprivacy_smime_set_store_cert(struct mailprivacy * privacy, + int enabled) +{ + store_cert = enabled; +} + +static int get_cert_from_sig(struct mailprivacy * privacy, + mailmessage * msg, + struct mailmime * mime) +{ + clistiter * cur; + struct mailmime * signed_mime; + struct mailmime * signature_mime; + int res; + char signature_filename[PATH_MAX]; + char quoted_signature_filename[PATH_MAX]; + char * email; + char * cert_file; + char store_cert_filename[PATH_MAX]; + char quoted_store_cert_filename[PATH_MAX]; + int r; + char command[PATH_MAX]; + + if (* cert_dir == '\0') + return MAIL_ERROR_INVAL; + + if (mime->mm_type != MAILMIME_MULTIPLE) + return MAIL_ERROR_INVAL; + + email = get_first_from_addr(mime); + if (email == NULL) + return MAIL_ERROR_INVAL; + + cert_file = get_cert_file(email); + if (cert_file != NULL) + return MAIL_NO_ERROR; + + /* get the two parts of the S/MIME message */ + + cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list); + if (cur == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + signed_mime = cur->data; + cur = clist_next(cur); + if (cur == NULL) { + res = MAIL_ERROR_INVAL; + goto err; + } + + signature_mime = cur->data; + + r = mailprivacy_fetch_decoded_to_file(privacy, + signature_filename, sizeof(signature_filename), + msg, signature_mime); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mail_quote_filename(quoted_signature_filename, + sizeof(quoted_signature_filename), signature_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_signature; + } + + snprintf(store_cert_filename, sizeof(store_cert_filename), + "%s/%s" CERTIFICATE_SUFFIX, cert_dir, email); + + r = mail_quote_filename(quoted_store_cert_filename, + sizeof(quoted_store_cert_filename), store_cert_filename); + if (r < 0) { + res = MAIL_ERROR_MEMORY; + goto unlink_signature; + } + + snprintf(command, sizeof(command), + "openssl pkcs7 -inform DER -in '%s' -out '%s' -print_certs 2>/dev/null", + quoted_signature_filename, quoted_store_cert_filename); + + r = system(command); + if (WEXITSTATUS(r) != 0) { + res = MAIL_ERROR_COMMAND; + goto unlink_signature; + } + + unlink(signature_filename); + + set_file(certificates, email, store_cert_filename); + + return MAIL_NO_ERROR; + + unlink_signature: + unlink(signature_filename); + err: + return res; +} + + +static void set_private_key(struct mailprivacy * privacy, + char * email, char * file) +{ + set_file(private_keys, email, file); +} + +#define PRIVATE_KEY_SUFFIX "-private-key.pem" + +void mailprivacy_smime_set_private_keys_dir(struct mailprivacy * privacy, + char * directory) +{ + DIR * dir; + struct dirent * ent; + + chash_clear(private_keys); + + if (directory == NULL) + return; + + if (* directory == '\0') + return; + + strncpy(private_keys_dir, directory, sizeof(private_keys_dir)); + private_keys_dir[sizeof(private_keys_dir) - 1] = '\0'; + + dir = opendir(directory); + if (dir == NULL) + return; + + while ((ent = readdir(dir)) != NULL) { + char filename[PATH_MAX]; + char email[PATH_MAX]; + char * p; + + snprintf(filename, sizeof(filename), + "%s/%s", directory, ent->d_name); + + strncpy(email, ent->d_name, sizeof(email)); + email[sizeof(email) - 1] = '\0'; + + p = strstr(email, PRIVATE_KEY_SUFFIX); + if (p == NULL) + continue; + + if (strlen(p) != sizeof(PRIVATE_KEY_SUFFIX) - 1) + continue; + + * p = 0; + + if (* email == '\0') + continue; + + set_private_key(privacy, email, filename); + } + closedir(dir); +} + +/* + - try private keys without passphrase and try those + for which we already have a passphrase, + - try recipient list and ask passphrase, + - then, ask passphrase for all private keys +*/ + +static int smime_command_passphrase(struct mailprivacy * privacy, + struct mailmessage * msg, + char * command, + char * userid, + char * stdoutfile, char * stderrfile) +{ + pid_t pid; + int passphrase_input[2]; + int fd_err; + int fd_out; + int r; + char * passphrase; + int bad_passphrase; + int res; + + bad_passphrase = 0; + + passphrase = NULL; + if (userid != NULL) + passphrase = get_passphrase(privacy, userid); + + fd_out = open(stdoutfile, O_RDWR | O_CREAT | O_TRUNC, 0600); + if (fd_out < 0) { + res = ERROR_SMIME_FILE; + goto err; + } + + fd_err = open(stderrfile, O_RDWR | O_CREAT | O_TRUNC, 0600); + if (fd_err < 0) { + res = ERROR_SMIME_FILE; + goto close_out; + } + + r = pipe(passphrase_input); + if (r < 0) { + res = ERROR_SMIME_FILE; + goto close_err; + } + + pid = fork(); + switch (pid) { + case -1: + return ERROR_SMIME_COMMAND; + + case 0: + /* child */ + { + int status; + + /* close unneeded fd */ + close(passphrase_input[1]); + + dup2(passphrase_input[0], 0); + close(passphrase_input[0]); + dup2(fd_out, 1); + close(fd_out); + dup2(fd_err, 2); + close(fd_err); + + status = system(command); + + exit(WEXITSTATUS(status)); + } + break; + + default: + /* parent */ + { + int status; + + /* close unneeded fd */ + close(fd_err); + close(fd_out); + close(passphrase_input[0]); + + if ((passphrase != NULL) && (strlen(passphrase) > 0)) { + write(passphrase_input[1], passphrase, strlen(passphrase)); + } + else { + /* dummy password */ + write(passphrase_input[1], "*dummy*", 7); + } + close(passphrase_input[1]); + + waitpid(pid, &status, 0); + + if (WEXITSTATUS(status) != 0) + bad_passphrase = 1; + } + break; + } + + if (bad_passphrase) { + if (userid != NULL) { + mailprivacy_smime_add_encryption_id(privacy, msg, userid); + return ERROR_SMIME_NOPASSPHRASE; + } + + return ERROR_SMIME_CHECK; + } + + return NO_ERROR_SMIME; + + close_err: + close(fd_err); + close_out: + close(fd_out); + err: + return res; +} + + + +#ifdef LIBETPAN_REENTRANT +static pthread_mutex_t encryption_id_hash_lock = PTHREAD_MUTEX_INITIALIZER; +#endif +static chash * encryption_id_hash = NULL; + +static clist * get_list(struct mailprivacy * privacy, mailmessage * msg) +{ + clist * encryption_id_list; + + encryption_id_list = NULL; + if (encryption_id_hash != NULL) { + chashdatum key; + chashdatum value; + int r; + + key.data = &msg; + key.len = sizeof(msg); + r = chash_get(encryption_id_hash, &key, &value); + if (r == 0) { + encryption_id_list = value.data; + } + } + + return encryption_id_list; +} + +void mailprivacy_smime_encryption_id_list_clear(struct mailprivacy * privacy, + mailmessage * msg) +{ + clist * encryption_id_list; + clistiter * iter; + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&encryption_id_hash_lock); +#endif + encryption_id_list = get_list(privacy, msg); + if (encryption_id_list != NULL) { + chashdatum key; + + for(iter = clist_begin(encryption_id_list) ; + iter != NULL ; iter = clist_next(iter)) { + char * str; + + str = clist_content(iter); + free(str); + } + clist_free(encryption_id_list); + + key.data = &msg; + key.len = sizeof(msg); + chash_delete(encryption_id_hash, &key, NULL); + + if (chash_count(encryption_id_hash) == 0) { + chash_free(encryption_id_hash); + encryption_id_hash = NULL; + } + } +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&encryption_id_hash_lock); +#endif +} + +clist * mailprivacy_smime_encryption_id_list(struct mailprivacy * privacy, + mailmessage * msg) +{ + clist * encryption_id_list; + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&encryption_id_hash_lock); +#endif + encryption_id_list = get_list(privacy, msg); +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&encryption_id_hash_lock); +#endif + + return encryption_id_list; +} + +static int mailprivacy_smime_add_encryption_id(struct mailprivacy * privacy, + mailmessage * msg, char * encryption_id) +{ + clist * encryption_id_list; + int r; + int res; + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_lock(&encryption_id_hash_lock); +#endif + + res = -1; + + encryption_id_list = get_list(privacy, msg); + if (encryption_id_list == NULL) { + if (encryption_id_hash == NULL) + encryption_id_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + + if (encryption_id_hash != NULL) { + encryption_id_list = clist_new(); + if (encryption_id_list != NULL) { + chashdatum key; + chashdatum value; + + key.data = &msg; + key.len = sizeof(msg); + value.data = encryption_id_list; + value.len = 0; + r = chash_set(encryption_id_hash, &key, &value, NULL); + if (r < 0) + clist_free(encryption_id_list); + } + } + } + + encryption_id_list = get_list(privacy, msg); + if (encryption_id_list != NULL) { + char * str; + + str = strdup(encryption_id); + if (str != NULL) { + r = clist_append(encryption_id_list, str); + if (r < 0) { + free(str); + } + else { + res = 0; + } + } + } + +#ifdef LIBETPAN_REENTRANT + pthread_mutex_unlock(&encryption_id_hash_lock); +#endif + + return res; +} + +static chash * passphrase_hash = NULL; + +int mailprivacy_smime_set_encryption_id(struct mailprivacy * privacy, + char * user_id, char * passphrase) +{ + chashdatum key; + chashdatum value; + int r; + char buf[MAX_EMAIL_SIZE]; + char * n; + + strncpy(buf, user_id, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + for(n = buf ; * n != '\0' ; n ++) + * n = toupper((unsigned char) * n); + + if (passphrase_hash == NULL) { + passphrase_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYALL); + if (passphrase_hash == NULL) + return MAIL_ERROR_MEMORY; + } + + key.data = buf; + key.len = strlen(buf) + 1; + value.data = passphrase; + value.len = strlen(passphrase) + 1; + + r = chash_set(passphrase_hash, &key, &value, NULL); + if (r < 0) { + return MAIL_ERROR_MEMORY; + } + + return MAIL_NO_ERROR; +} + +static char * get_passphrase(struct mailprivacy * privacy, + char * user_id) +{ + chashdatum key; + chashdatum value; + int r; + char * passphrase; + char buf[MAX_EMAIL_SIZE]; + char * n; + + strncpy(buf, user_id, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + for(n = buf ; * n != '\0' ; n ++) + * n = toupper((unsigned char) * n); + + if (passphrase_hash == NULL) + return NULL; + + key.data = buf; + key.len = strlen(buf) + 1; + + r = chash_get(passphrase_hash, &key, &value); + if (r < 0) + return NULL; + + passphrase = strdup(value.data); + + return passphrase; +} Added: freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_smime.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_smime.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,94 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_smime.h,v 1.4 2005/11/21 16:17:57 hoa Exp $ + */ + +#ifndef MAILPRIVACY_SMIME_H + +#define MAILPRIVACY_SMIME_H + +#include <libetpan/mailprivacy_types.h> + +int mailprivacy_smime_init(struct mailprivacy * privacy); + +void mailprivacy_smime_done(struct mailprivacy * privacy); + +void mailprivacy_smime_set_cert_dir(struct mailprivacy * privacy, + char * directory); + + +/* + set directory where certificates of authority certifications are + stored. +*/ + +void mailprivacy_smime_set_CA_dir(struct mailprivacy * privacy, + char * directory); + + +/* + to disable the verification of signers certificates of a + signed message. +*/ + +void mailprivacy_smime_set_CA_check(struct mailprivacy * privacy, + int enabled); + + +/* + to store certificates of signed messages +*/ + +void mailprivacy_smime_set_store_cert(struct mailprivacy * privacy, + int enabled); + +/* + set directory where private keys are stored. + name of the files in that directory must be in form : + [email-address]-private-key.pem +*/ + +void mailprivacy_smime_set_private_keys_dir(struct mailprivacy * privacy, + char * directory); + + +clist * mailprivacy_smime_encryption_id_list(struct mailprivacy * privacy, + mailmessage * msg); + +void mailprivacy_smime_encryption_id_list_clear(struct mailprivacy * privacy, + mailmessage * msg); + +int mailprivacy_smime_set_encryption_id(struct mailprivacy * privacy, + char * user_id, char * passphrase); + +#endif Added: freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_tools.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_tools.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1311 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_tools.c,v 1.10 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailprivacy_tools.h" + +#include <stdlib.h> +#include <string.h> +#include <libgen.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <libetpan/mailmessage.h> +#include <ctype.h> +#include "mailprivacy.h" +#include <libetpan/libetpan-config.h> +#include <libetpan/data_message_driver.h> + +void mailprivacy_mime_clear(struct mailmime * mime) +{ + struct mailmime_data * data; + clistiter * cur; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + data = mime->mm_data.mm_single; + if (data != NULL) { + if (data->dt_type == MAILMIME_DATA_FILE) + unlink(data->dt_data.dt_filename); + } + break; + + case MAILMIME_MULTIPLE: + data = mime->mm_data.mm_multipart.mm_preamble; + if (data != NULL) { + if (data->dt_type == MAILMIME_DATA_FILE) + unlink(data->dt_data.dt_filename); + } + data = mime->mm_data.mm_multipart.mm_epilogue; + if (data != NULL) { + if (data->dt_type == MAILMIME_DATA_FILE) + unlink(data->dt_data.dt_filename); + } + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * submime; + + submime = clist_content(cur); + + mailprivacy_mime_clear(submime); + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + mailprivacy_mime_clear(mime->mm_data.mm_message.mm_msg_mime); + } + break; + } +} + + +static FILE * get_tmp_file(char * filename) +{ + int fd; + mode_t old_mask; + FILE * f; + + old_mask = umask(0077); + fd = mkstemp(filename); + umask(old_mask); + if (fd == -1) + return NULL; + + f = fdopen(fd, "r+"); + if (f == NULL) { + close(fd); + unlink(filename); + } + + return f; +} + +FILE * mailprivacy_get_tmp_file(struct mailprivacy * privacy, + char * filename, size_t size) +{ + snprintf(filename, size, "%s/libetpan-privacy-XXXXXX", privacy->tmp_dir); + return get_tmp_file(filename); +} + +int mailprivacy_get_tmp_filename(struct mailprivacy * privacy, + char * filename, size_t size) +{ + FILE * f; + + f = mailprivacy_get_tmp_file(privacy, filename, size); + if (f == NULL) + return MAIL_ERROR_FILE; + + fclose(f); + + return MAIL_NO_ERROR; +} + +static char * dup_file(struct mailprivacy * privacy, + char * source_filename) +{ + char filename[PATH_MAX]; + FILE * dest_f; + int r; + struct stat stat_info; + char * dest_filename; + char * mapping; + size_t written; + int fd; + + dest_f = mailprivacy_get_tmp_file(privacy, filename, sizeof(filename)); + if (dest_f == NULL) + goto err; + + dest_filename = strdup(filename); + if (dest_filename == NULL) + goto close_dest; + + fd = open(source_filename, O_RDONLY); + if (fd < 0) + goto free_dest; + + r = fstat(fd, &stat_info); + if (r < 0) + goto close_src; + + mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == (char *)MAP_FAILED) + goto close_src; + + written = fwrite(mapping, 1, stat_info.st_size, dest_f); + if (written != (size_t) stat_info.st_size) + goto unmap; + + munmap(mapping, stat_info.st_size); + close(fd); + fclose(dest_f); + + return dest_filename; + + unmap: + munmap(mapping, stat_info.st_size); + close_src: + close(fd); + free_dest: + free(dest_filename); + close_dest: + fclose(dest_f); + err: + return NULL; +} + + +/* + mime_data_replace() + + write a mime part to a file and change the reference of mailmime_data + to the file. +*/ + +static int mime_data_replace(struct mailprivacy * privacy, + int encoding_type, + struct mailmime_data * data, + int reencode) +{ + char filename[PATH_MAX]; + FILE * f; + size_t written; + char * dup_filename; + int res; + int r; + int decoded; + + if (data->dt_type != MAILMIME_DATA_TEXT) { + res = MAIL_NO_ERROR; + goto err; + } + + f = mailprivacy_get_tmp_file(privacy, filename, sizeof(filename)); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + decoded = 0; + if (reencode) { + if (encoding_type != -1) { + char * content; + size_t content_len; + size_t cur_token; + + cur_token = 0; + r = mailmime_part_parse(data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length, + &cur_token, encoding_type, &content, &content_len); + + if (r == MAILIMF_NO_ERROR) { + /* write decoded */ + written = fwrite(content, 1, content_len, f); + if (written != content_len) { + fclose(f); + unlink(filename); + res = MAIL_ERROR_FILE; + goto err; + } + mmap_string_unref(content); + + decoded = 1; + data->dt_encoded = 0; + } + } + } + + if (!decoded) { + written = fwrite(data->dt_data.dt_text.dt_data, 1, + data->dt_data.dt_text.dt_length, f); + if (written != data->dt_data.dt_text.dt_length) { + fclose(f); + unlink(filename); + res = MAIL_ERROR_FILE; + goto err; + } + } + + fclose(f); + + dup_filename = strdup(filename); + if (dup_filename == NULL) { + unlink(filename); + res = MAIL_ERROR_MEMORY; + goto err; + } + + data->dt_type = MAILMIME_DATA_FILE; + data->dt_data.dt_filename = dup_filename; + + return MAIL_NO_ERROR; + + err: + return res; +} + + +/* + recursive_replace_single_parts() + + write all parts of the given mime part to file. +*/ + +static int recursive_replace_single_parts(struct mailprivacy * privacy, + struct mailmime * mime, int reencode) +{ + int r; + int res; + clistiter * cur; + + mime->mm_mime_start = NULL; + + switch(mime->mm_type) { + case MAILMIME_SINGLE: + if (mime->mm_data.mm_single != NULL) { + int encoding_type; + struct mailmime_single_fields single_fields; + + mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, + mime->mm_content_type); + + if (single_fields.fld_encoding != NULL) + encoding_type = single_fields.fld_encoding->enc_type; + else + encoding_type = -1; + + r = mime_data_replace(privacy, encoding_type, + mime->mm_data.mm_single, reencode); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + break; + + case MAILMIME_MULTIPLE: + if (mime->mm_data.mm_multipart.mm_preamble != NULL) { + r = mime_data_replace(privacy, -1, + mime->mm_data.mm_multipart.mm_preamble, reencode); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + if (mime->mm_data.mm_multipart.mm_epilogue != NULL) { + r = mime_data_replace(privacy, -1, + mime->mm_data.mm_multipart.mm_epilogue, reencode); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = clist_content(cur); + + r = recursive_replace_single_parts(privacy, child, reencode); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + r = recursive_replace_single_parts(privacy, + mime->mm_data.mm_message.mm_msg_mime, reencode); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + break; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +/* + mailprivacy_get_mime() + + parse the message in MIME structure, + all single MIME parts are stored in files. + + privacy can be set to NULL to disable privacy check. +*/ + +int mailprivacy_get_mime(struct mailprivacy * privacy, + int check_privacy, int reencode, + char * content, size_t content_len, + struct mailmime ** result_mime) +{ + struct mailmime * mime; + mailmessage * msg; + int r; + int res; + +#if 0 + int check_privacy; + + check_privacy = (privacy != NULL); +#endif + + /* + use message data driver, get bodystructure and + convert all the data part in MAILMIME_SINGLE to files. + */ + + msg = data_message_init(content, content_len); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + +#if 0 + if (msg->mime == NULL) { + if (check_privacy) { + r = mailprivacy_msg_get_bodystructure(privacy, msg, &mime); + } + else { + /* + don't use etpan_msg_get_bodystructure because it is not useful + and to avoid loops due to security part + */ + r = mailmessage_get_bodystructure(msg, &mime); + } + } + else { + mime = msg->mime; + } +#endif + + if (check_privacy) + r = mailprivacy_msg_get_bodystructure(privacy, msg, &mime); + else + r = mailmessage_get_bodystructure(msg, &mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_msg; + } + + /* + should be done so that the MIME structure need not to be unregistered. + */ + mailprivacy_recursive_unregister_mime(privacy, mime); + + r = recursive_replace_single_parts(privacy, mime, reencode); + if (r != MAIL_NO_ERROR) { + res = r; + goto clear_mime; + } + + data_message_detach_mime(msg); +#if 0 + if (check_privacy) + mailprivacy_msg_flush(privacy, msg); + else + mailmessage_flush(msg); +#endif + mailprivacy_msg_flush(privacy, msg); + mailmessage_free(msg); + + * result_mime = mime; + + return MAIL_NO_ERROR; + + clear_mime: + mailprivacy_mime_clear(mime); + mailprivacy_msg_flush(privacy, msg); + free_msg: + mailmessage_free(msg); + err: + return res; +} + +#ifndef LIBETPAN_SYSTEM_BASENAME +static char * libetpan_basename(char * filename) +{ + char * next; + char * p; + + p = filename; + next = strchr(p, '/'); + + while (next != NULL) { + p = next; + next = strchr(p + 1, '/'); + } + + if (p == filename) + return filename; + else + return p + 1; +} +#else +#define libetpan_basename(a) basename(a) +#endif + +struct mailmime * +mailprivacy_new_file_part(struct mailprivacy * privacy, + char * filename, + char * default_content_type, int default_encoding) +{ + char basename_buf[PATH_MAX]; + char * name; + struct mailmime_mechanism * encoding; + struct mailmime_content * content; + struct mailmime * mime; + int r; + char * dup_filename; + struct mailmime_fields * mime_fields; + int encoding_type; + char * content_type_str; + int do_encoding; + + if (filename != NULL) { + strncpy(basename_buf, filename, PATH_MAX); + name = libetpan_basename(basename_buf); + } + else { + name = NULL; + } + + encoding = NULL; + + /* default content-type */ + if (default_content_type == NULL) + content_type_str = "application/octet-stream"; + else + content_type_str = default_content_type; + + content = mailmime_content_new_with_str(content_type_str); + if (content == NULL) { + goto free_content; + } + + do_encoding = 1; + if (content->ct_type->tp_type == MAILMIME_TYPE_COMPOSITE_TYPE) { + struct mailmime_composite_type * composite; + + composite = content->ct_type->tp_data.tp_composite_type; + + switch (composite->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + if (strcasecmp(content->ct_subtype, "rfc822") == 0) + do_encoding = 0; + break; + + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + do_encoding = 0; + break; + } + } + + if (do_encoding) { + if (default_encoding == -1) + encoding_type = MAILMIME_MECHANISM_BASE64; + else + encoding_type = default_encoding; + + /* default Content-Transfer-Encoding */ + encoding = mailmime_mechanism_new(encoding_type, NULL); + if (encoding == NULL) { + goto free_content; + } + } + + mime_fields = mailmime_fields_new_with_data(encoding, + NULL, NULL, NULL, NULL); + if (mime_fields == NULL) { + goto free_content; + } + + mime = mailmime_new_empty(content, mime_fields); + if (mime == NULL) { + goto free_mime_fields; + } + + if ((filename != NULL) && (mime->mm_type == MAILMIME_SINGLE)) { + /* + duplicates the file so that the file can be deleted when + the MIME part is done + */ + dup_filename = dup_file(privacy, filename); + if (dup_filename == NULL) { + goto free_mime; + } + + r = mailmime_set_body_file(mime, dup_filename); + if (r != MAILIMF_NO_ERROR) { + free(dup_filename); + goto free_mime; + } + } + + return mime; + + free_mime: + mailmime_free(mime); + goto err; + free_mime_fields: + mailmime_fields_free(mime_fields); + mailmime_content_free(content); + goto err; + free_content: + if (encoding != NULL) + mailmime_mechanism_free(encoding); + if (content != NULL) + mailmime_content_free(content); + err: + return NULL; +} + + +int mailmime_substitute(struct mailmime * old_mime, + struct mailmime * new_mime) +{ + struct mailmime * parent; + + parent = old_mime->mm_parent; + if (parent == NULL) + return MAIL_ERROR_INVAL; + + if (old_mime->mm_parent_type == MAILMIME_MESSAGE) + parent->mm_data.mm_message.mm_msg_mime = new_mime; + else /* MAILMIME_MULTIPLE */ + old_mime->mm_multipart_pos->data = new_mime; + new_mime->mm_parent = parent; + new_mime->mm_parent_type = old_mime->mm_parent_type; + + /* detach old_mime */ + old_mime->mm_parent = NULL; + old_mime->mm_parent_type = MAILMIME_NONE; + + return MAIL_NO_ERROR; +} + + + +/* write mime headers and body to a file, CR LF fixed */ + +int mailprivacy_fetch_mime_body_to_file(struct mailprivacy * privacy, + char * filename, size_t size, + mailmessage * msg, struct mailmime * mime) +{ + int r; + int res; + FILE * f; + char * content; + size_t content_len; + int col; + + if (mime->mm_parent_type == MAILMIME_NONE) { + res = MAIL_ERROR_INVAL; + goto err; + } + + f = mailprivacy_get_tmp_file(privacy, filename, size); + if (f == NULL) { + res = MAIL_ERROR_FETCH; + goto err; + } + + r = mailprivacy_msg_fetch_section_mime(privacy, msg, mime, + &content, &content_len); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FETCH; + goto close; + } + + col = 0; + r = mailimf_string_write(f, &col, content, content_len); + mailprivacy_msg_fetch_result_free(privacy, msg, content); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto close; + } + + r = mailprivacy_msg_fetch_section(privacy, msg, mime, + &content, &content_len); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FETCH; + goto close; + } + + r = mailimf_string_write(f, &col, content, content_len); + mailprivacy_msg_fetch_result_free(privacy, msg, content); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto close; + } + + fclose(f); + + return MAIL_NO_ERROR; + + close: + fclose(f); + unlink(filename); + err: + return res; +} + + +int mailprivacy_get_part_from_file(struct mailprivacy * privacy, + int check_security, int reencode, char * filename, + struct mailmime ** result_mime) +{ + int fd; + struct mailmime * mime; + int r; + struct stat stat_info; + int res; + char * mapping; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + r = fstat(fd, &stat_info); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close; + } + + mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == (char *)MAP_FAILED) { + res = MAIL_ERROR_FILE; + goto close; + } + + mime = NULL; + /* check recursive parts if privacy is set */ + r = mailprivacy_get_mime(privacy, check_security, reencode, + mapping, stat_info.st_size, &mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto unmap; + } + + if (mime->mm_type == MAILMIME_MESSAGE) { + struct mailmime * submime; + + submime = mime->mm_data.mm_message.mm_msg_mime; + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + mailmime_remove_part(submime); + mailmime_free(mime); + + mime = submime; + } + } + + munmap(mapping, stat_info.st_size); + + close(fd); + + * result_mime = mime; + + return MAIL_NO_ERROR; + + unmap: + munmap(mapping, stat_info.st_size); + close: + close(fd); + err: + return res; +} + +int mail_quote_filename(char * result, size_t size, char * path) +{ + char * p; + char * result_p; + size_t remaining; + + result_p = result; + remaining = size; + + for(p = path ; * p != '\0' ; p ++) { + int quote_not_needed; + +#if 0 + quote_not_needed = (isalpha(* p) || isdigit(* p) || (* p == '/')); +#else + quote_not_needed = (* p != '\\') && (* p != '\'') && (* p != '\"'); +#endif + if (quote_not_needed) { + if (remaining > 0) { + * result_p = * p; + result_p ++; + remaining --; + } + else { + result[size - 1] = '\0'; + return -1; + } + } + else { + if (remaining >= 2) { + * result_p = '\\'; + result_p ++; + * result_p = * p; + result_p ++; + remaining -= 2; + } + else { + result[size - 1] = '\0'; + return -1; + } + } + } + if (remaining > 0) { + * result_p = '\0'; + } + else { + result[size - 1] = '\0'; + return -1; + } + + return 0; +} + + +static void prepare_mime_single(struct mailmime * mime) +{ + struct mailmime_single_fields single_fields; + int encoding; + int r; + + if (mime->mm_mime_fields != NULL) { + mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, + mime->mm_content_type); + if (single_fields.fld_encoding != NULL) { + encoding = single_fields.fld_encoding->enc_type; + switch (encoding) { + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_BINARY: + single_fields.fld_encoding->enc_type = + MAILMIME_MECHANISM_QUOTED_PRINTABLE; + break; + } + } + else { + struct mailmime_mechanism * mechanism; + struct mailmime_field * field; + + mechanism = + mailmime_mechanism_new(MAILMIME_MECHANISM_QUOTED_PRINTABLE, NULL); + if (mechanism == NULL) + return; + + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, mechanism, NULL, NULL, 0, NULL, NULL); + if (field == NULL) { + mailmime_mechanism_free(mechanism); + return; + } + + r = clist_append(mime->mm_mime_fields->fld_list, field); + if (r < 0) { + mailmime_field_free(field); + return; + } + } + } + + if (mime->mm_type == MAILMIME_SINGLE) { + switch (mime->mm_data.mm_single->dt_encoding) { + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_BINARY: + mime->mm_data.mm_single->dt_encoding = + MAILMIME_MECHANISM_QUOTED_PRINTABLE; + mime->mm_data.mm_single->dt_encoded = 0; + break; + } + } +} + +/* + mailprivacy_prepare_mime() + + we assume we built ourself the message. +*/ + +void mailprivacy_prepare_mime(struct mailmime * mime) +{ + clistiter * cur; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + if (mime->mm_data.mm_single != NULL) { + prepare_mime_single(mime); + } + break; + + case MAILMIME_MULTIPLE: + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = clist_content(cur); + + mailprivacy_prepare_mime(child); + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime) { + mailprivacy_prepare_mime(mime->mm_data.mm_message.mm_msg_mime); + } + break; + } +} + + +char * mailprivacy_dup_imf_file(struct mailprivacy * privacy, + char * source_filename) +{ + char filename[PATH_MAX]; + FILE * dest_f; + int r; + struct stat stat_info; + char * dest_filename; + char * mapping; + int fd; + int col; + + dest_f = mailprivacy_get_tmp_file(privacy, + filename, sizeof(filename)); + if (dest_f == NULL) + goto err; + + dest_filename = strdup(filename); + if (dest_filename == NULL) + goto close_dest; + + fd = open(source_filename, O_RDONLY); + if (fd < 0) + goto free_dest; + + r = fstat(fd, &stat_info); + if (r < 0) + goto close_src; + + mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == (char *)MAP_FAILED) + goto close_src; + + col = 0; + r = mailimf_string_write(dest_f, &col, mapping, stat_info.st_size); + if (r != MAILIMF_NO_ERROR) + goto unmap; + + munmap(mapping, stat_info.st_size); + close(fd); + fclose(dest_f); + + return dest_filename; + + unmap: + munmap(mapping, stat_info.st_size); + close_src: + close(fd); + free_dest: + free(dest_filename); + close_dest: + fclose(dest_f); + err: + return NULL; +} + +/* TODO : better function to duplicate mime fields, currenly such inelegant */ + +struct mailmime_fields * +mailprivacy_mime_fields_dup(struct mailprivacy * privacy, + struct mailmime_fields * mime_fields) +{ + FILE * f; + char tmp_file[PATH_MAX]; + int col; + int r; + struct mailmime_fields * dup_mime_fields; + int fd; + char * mapping; + struct stat stat_info; + struct mailimf_fields * fields; + size_t cur_token; + + f = mailprivacy_get_tmp_file(privacy, tmp_file, sizeof(tmp_file)); + if (f == NULL) + goto err; + + col = 0; + r = mailmime_fields_write(f, &col, mime_fields); + if (r != MAILIMF_NO_ERROR) + goto unlink; + + fflush(f); + + fd = fileno(f); + if (fd == -1) + goto unlink; + + r = fstat(fd, &stat_info); + if (r < 0) + goto unlink; + + mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == (char *)MAP_FAILED) + goto unlink; + + cur_token = 0; + r = mailimf_optional_fields_parse(mapping, stat_info.st_size, + &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) + goto unmap; + + r = mailmime_fields_parse(fields, &dup_mime_fields); + mailimf_fields_free(fields); + if (r != MAILIMF_NO_ERROR) + goto unmap; + + munmap(mapping, stat_info.st_size); + fclose(f); + unlink(tmp_file); + + return dup_mime_fields; + + unmap: + munmap(mapping, stat_info.st_size); + unlink: + fclose(f); + unlink(tmp_file); + err: + return NULL; +} + + + +struct mailmime_parameter * +mailmime_parameter_dup(struct mailmime_parameter * param) +{ + char * name; + char * value; + struct mailmime_parameter * dup_param; + + name = strdup(param->pa_name); + if (name == NULL) + goto err; + + value = strdup(param->pa_value); + if (value == NULL) + goto free_name; + + dup_param = mailmime_parameter_new(name, value); + if (dup_param == NULL) + goto free_value; + + return dup_param; + + free_value: + free(value); + free_name: + free(name); + err: + return NULL; +} + +struct mailmime_composite_type * +mailmime_composite_type_dup(struct mailmime_composite_type * composite_type) +{ + struct mailmime_composite_type * dup_composite; + char * token; + + token = NULL; + if (composite_type->ct_token != NULL) { + token = strdup(composite_type->ct_token); + if (token == NULL) + goto err; + } + + dup_composite = mailmime_composite_type_new(composite_type->ct_type, token); + if (dup_composite == NULL) + goto free_token; + + return dup_composite; + + free_token: + if (token != NULL) + free(token); + err: + return NULL; +} + +struct mailmime_discrete_type * +mailmime_discrete_type_dup(struct mailmime_discrete_type * discrete_type) +{ + struct mailmime_discrete_type * dup_discrete; + char * extension; + + extension = NULL; + if (discrete_type->dt_extension != NULL) { + extension = strdup(discrete_type->dt_extension); + if (extension == NULL) + goto err; + } + + dup_discrete = mailmime_discrete_type_new(discrete_type->dt_type, extension); + if (dup_discrete == NULL) + goto free_extension; + + return dup_discrete; + + free_extension: + if (extension != NULL) + free(extension); + err: + return NULL; +} + +struct mailmime_type * mailmime_type_dup(struct mailmime_type * type) +{ + struct mailmime_type * dup_type; + struct mailmime_discrete_type * discrete_type; + struct mailmime_composite_type * composite_type; + + discrete_type = NULL; + composite_type = NULL; + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + discrete_type = + mailmime_discrete_type_dup(type->tp_data.tp_discrete_type); + if (discrete_type == NULL) + goto err; + break; + + composite_type = + mailmime_composite_type_dup(type->tp_data.tp_composite_type); + if (composite_type == NULL) + goto free_discrete; + } + + dup_type = mailmime_type_new(type->tp_type, discrete_type, composite_type); + if (dup_type == NULL) + goto free_composite; + + return dup_type; + + free_composite: + if (composite_type != NULL) + mailmime_composite_type_free(composite_type); + free_discrete: + if (discrete_type != NULL) + mailmime_discrete_type_free(discrete_type); + err: + return NULL; +} + +struct mailmime_content * +mailmime_content_dup(struct mailmime_content * content) +{ + clist * list; + struct mailmime_type * type; + int r; + struct mailmime_content * dup_content; + char * subtype; + + type = mailmime_type_dup(content->ct_type); + if (type == NULL) + goto err; + + subtype = strdup(content->ct_subtype); + if (subtype == NULL) + goto free_type; + + list = clist_new(); + if (list == NULL) + goto free_subtype; + + if (content->ct_parameters != NULL) { + clistiter * cur; + + for(cur = clist_begin(content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = mailmime_parameter_dup(clist_content(cur)); + if (param == NULL) + goto free_list; + + r = clist_append(list, param); + if (r < 0) { + mailmime_parameter_free(param); + goto free_list; + } + } + } + + dup_content = mailmime_content_new(type, subtype, list); + if (dup_content == NULL) + goto free_list; + + return dup_content; + + free_list: + clist_foreach(list, (clist_func) mailmime_parameter_free, NULL); + free_subtype: + free(subtype); + free_type: + mailmime_type_free(type); + err: + return NULL; +} + + +struct mailmime_parameter * +mailmime_param_new_with_data(char * name, char * value) +{ + char * param_name; + char * param_value; + struct mailmime_parameter * param; + + param_name = strdup(name); + if (param_name == NULL) + goto err; + + param_value = strdup(value); + if (param_value == NULL) + goto free_name; + + param = mailmime_parameter_new(param_name, param_value); + if (param == NULL) + goto free_value; + + return param; + + free_value: + free(param_value); + free_name: + free(param_name); + err: + return NULL; +} + + +int mailprivacy_fetch_decoded_to_file(struct mailprivacy * privacy, + char * filename, size_t size, + mailmessage * msg, struct mailmime * mime) +{ + int r; + int res; + FILE * f; + char * content; + size_t content_len; + size_t written; + struct mailmime_single_fields single_fields; + int encoding; + size_t cur_token; + char * parsed_content; + size_t parsed_content_len; + + mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, + mime->mm_content_type); + if (single_fields.fld_encoding != NULL) + encoding = single_fields.fld_encoding->enc_type; + else + encoding = MAILMIME_MECHANISM_8BIT; + + r = mailprivacy_msg_fetch_section(privacy, msg, mime, + &content, &content_len); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FETCH; + goto err; + } + + cur_token = 0; + r = mailmime_part_parse(content, content_len, &cur_token, + encoding, &parsed_content, &parsed_content_len); + mailprivacy_msg_fetch_result_free(privacy, msg, content); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_PARSE; + goto err; + } + + f = mailprivacy_get_tmp_file(privacy, filename, size); + if (f == NULL) { + res = MAIL_ERROR_FETCH; + goto free_fetch; + } + written = fwrite(parsed_content, 1, parsed_content_len, f); + if (written != parsed_content_len) { + res = MAIL_ERROR_FILE; + goto close; + } + fclose(f); + + mmap_string_unref(parsed_content); + + return MAIL_NO_ERROR; + + close: + fclose(f); + unlink(filename); + free_fetch: + mmap_string_unref(parsed_content); + err: + return res; +} + Added: freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_tools.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_tools.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,105 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_tools.h,v 1.6 2005/12/21 23:49:23 hoa Exp $ + */ + +#ifndef MAIL_PRIVACY_TOOLS_H + +#define MAIL_PRIVACY_TOOLS_H + +#include <libetpan/mailmessage.h> +#include <libetpan/mailprivacy_types.h> + +void mailprivacy_mime_clear(struct mailmime * mime); + +FILE * mailprivacy_get_tmp_file(struct mailprivacy * privacy, + char * filename, size_t size); + +int mailprivacy_get_tmp_filename(struct mailprivacy * privacy, + char * filename, size_t size); + +struct mailmime * +mailprivacy_new_file_part(struct mailprivacy * privacy, + char * filename, + char * default_content_type, int default_encoding); + +int mailmime_substitute(struct mailmime * old_mime, + struct mailmime * new_mime); + +int mailprivacy_fetch_mime_body_to_file(struct mailprivacy * privacy, + char * filename, size_t size, + mailmessage * msg, struct mailmime * mime); + +int mailprivacy_get_part_from_file(struct mailprivacy * privacy, + int check_privacy, int reencode, + char * filename, + struct mailmime ** result_mime); + +int mail_quote_filename(char * result, size_t size, char * path); + +void mailprivacy_prepare_mime(struct mailmime * mime); + +char * mailprivacy_dup_imf_file(struct mailprivacy * privacy, + char * source_filename); + +struct mailmime_fields * +mailprivacy_mime_fields_dup(struct mailprivacy * privacy, + struct mailmime_fields * mime_fields); + +struct mailmime_parameter * +mailmime_parameter_dup(struct mailmime_parameter * param); + +struct mailmime_composite_type * +mailmime_composite_type_dup(struct mailmime_composite_type * composite_type); + +struct mailmime_discrete_type * +mailmime_discrete_type_dup(struct mailmime_discrete_type * discrete_type); + +struct mailmime_type * mailmime_type_dup(struct mailmime_type * type); + +struct mailmime_content * +mailmime_content_dup(struct mailmime_content * content); + +struct mailmime_parameter * +mailmime_param_new_with_data(char * name, char * value); + +int mailprivacy_fetch_decoded_to_file(struct mailprivacy * privacy, + char * filename, size_t size, + mailmessage * msg, struct mailmime * mime); + +int mailprivacy_get_mime(struct mailprivacy * privacy, + int check_privacy, int reencode, + char * content, size_t content_len, + struct mailmime ** result_mime); + +#endif Added: freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/engine/mailprivacy_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,83 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailprivacy_types.h,v 1.4 2005/11/21 16:17:57 hoa Exp $ + */ + +#ifndef MAIL_PRIVACY_TYPES_H + +#define MAIL_PRIVACY_TYPES_H + +#include <libetpan/chash.h> +#include <libetpan/carray.h> +#include <libetpan/mailmessage.h> +#include <libetpan/mailmime.h> + +struct mailprivacy { + char * tmp_dir; /* working tmp directory */ + chash * msg_ref; /* mailmessage => present or not */ + chash * mmapstr; /* mmapstring => present or not present */ + chash * mime_ref; /* mime => present or not */ + carray * protocols; + int make_alternative; + /* if make_alternative is 0, replaces the part with decrypted + part, if 1, adds a multipart/alternative and put the decrypted + and encrypted part as subparts. + */ +}; + +struct mailprivacy_encryption { + char * name; + char * description; + + int (* encrypt)(struct mailprivacy *, + mailmessage *, + struct mailmime *, struct mailmime **); +}; + +struct mailprivacy_protocol { + char * name; + char * description; + + /* introduced to easy the port to sylpheed */ + int (* is_encrypted)(struct mailprivacy *, + mailmessage *, struct mailmime *); + + int (* decrypt)(struct mailprivacy *, + mailmessage *, struct mailmime *, + struct mailmime **); + + int encryption_count; + struct mailprivacy_encryption * encryption_tab; +}; + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,2 @@ +.libs +*.la Added: freeswitch/trunk/libs/libetpan/src/low-level/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,22 @@ +# Generated automatically from Makefile.in by configure. +top_builddir = ../.. + +TARGET = liblow-level + +LDFLAGS = + +SUBLIBS = imap/libimap.la \ + imf/libimf.la \ + maildir/libmaildir.la \ + mbox/libmbox.la \ + mh/libmh.la \ + mime/libmime.la \ + nntp/libnntp.la \ + pop3/libpop3.la \ + smtp/libsmtp.la + + +SUBDIRS = imap imf maildir mbox mh mime nntp pop3 smtp + +include $(top_builddir)/Rules + Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,38 @@ +top_builddir = ../../.. + +TARGET = libimap +HEADERS = mailimap_helper.h mailimap.h \ + mailimap_types.h mailimap_types_helper.h \ + mailimap_socket.h mailimap_ssl.h \ + mailimap_extension.h mailimap_extension_types.h \ + annotatemore.h annotatemore_types.h \ + acl.h acl_types.h \ + uidplus.h uidplus_types.h + +SOURCES = mailimap_types.c mailimap_types_helper.c \ + mailimap_sender.c \ + mailimap_keywords.c \ + mailimap_parser.c \ + mailimap.c \ + mailimap_helper.c \ + mailimap_socket.c \ + mailimap_ssl.c \ + mailimap_print.c \ + mailimap_extension.c \ + annotatemore.c \ + annotatemore_parser.c \ + annotatemore_sender.c \ + annotatemore_types.c \ + acl.c \ + acl_parser.c \ + acl_sender.c \ + acl_types.c \ + uidplus.c \ + uidplus_sender.c \ + uidplus_types.c \ + uidplus_parser.c \ + + +INCLUDES = -I$(srcdir)/data-types + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/TODO ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/TODO Wed Dec 20 15:28:56 2006 @@ -0,0 +1,4 @@ +- literal data send progress +- implement draft-16 (rfc 2822 things) +- more efficient parser + Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/acl.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/acl.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,388 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimap.h" +#include "mailimap_extension.h" +#include "acl.h" +#include "acl_types.h" +#include "acl_parser.h" +#include "acl_sender.h" + +#include <stdlib.h> + +LIBETPAN_EXPORT +struct mailimap_extension_api mailimap_extension_acl = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* name */ "ACL", + /* extension_id */ MAILIMAP_EXTENSION_ACL, + /* parser */ mailimap_acl_parse, + /* free */ mailimap_acl_free, +#else + .name = "ACL", + .extension_id = MAILIMAP_EXTENSION_ACL, + .parser = mailimap_acl_parse, + .free = mailimap_acl_free, +#endif +}; + +LIBETPAN_EXPORT +int mailimap_acl_setacl(mailimap * session, + const char * mailbox, + const char * identifier, + const char * mod_rights) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_setacl_send(session->imap_stream, + mailbox, identifier, mod_rights); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXTENSION; + } +} + +LIBETPAN_EXPORT +int mailimap_acl_deleteacl(mailimap * session, + const char * mailbox, + const char * identifier) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_deleteacl_send(session->imap_stream, + mailbox, identifier); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXTENSION; + } +} + +LIBETPAN_EXPORT +int mailimap_acl_getacl(mailimap * session, + const char * mailbox, + clist ** result) +{ + struct mailimap_response * response; + struct mailimap_extension_data * ext_data; + clistiter * cur; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_getacl_send(session->imap_stream, + mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = clist_new(); + if (* result == NULL) + return MAILIMAP_ERROR_MEMORY; + + /* get all acl_data received and copy it to result */ + for (cur = clist_begin(session->imap_response_info->rsp_extension_list); + cur != NULL; cur = clist_next(cur)) { + ext_data = (struct mailimap_extension_data *) clist_content(cur); + if ( + ext_data->ext_extension->ext_id == MAILIMAP_EXTENSION_ACL && + ext_data->ext_type == MAILIMAP_ACL_TYPE_ACL_DATA) { + r = clist_append((* result), ext_data->ext_data); + if (r != 0) + return MAILIMAP_ERROR_MEMORY; + + ext_data->ext_data = NULL; + ext_data->ext_type = -1; + } + } + + clist_foreach(session->imap_response_info->rsp_extension_list, + (clist_func) mailimap_extension_data_free, NULL); + clist_free(session->imap_response_info->rsp_extension_list); + session->imap_response_info->rsp_extension_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXTENSION; + } +} + +LIBETPAN_EXPORT +int mailimap_acl_listrights(mailimap * session, + const char * mailbox, + const char * identifier, + struct mailimap_acl_listrights_data ** result) +{ + struct mailimap_response * response; + struct mailimap_extension_data * ext_data; + clistiter * cur; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_listrights_send(session->imap_stream, + mailbox, identifier); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = NULL; + + /* in rsp_extension_list there is at most one listrights_data */ + for (cur = clist_begin(session->imap_response_info->rsp_extension_list); + cur != NULL; cur = clist_next(cur)) { + ext_data = (struct mailimap_extension_data *) clist_content(cur); + if ( + ext_data->ext_extension->ext_id == MAILIMAP_EXTENSION_ACL && + ext_data->ext_type == MAILIMAP_ACL_TYPE_LISTRIGHTS_DATA) { + * result = (struct mailimap_acl_listrights_data *)ext_data->ext_data; + /* remove the element from rsp_extension_list */ + clist_delete(session->imap_response_info->rsp_extension_list, cur); + + break; + } + } + + clist_foreach(session->imap_response_info->rsp_extension_list, + (clist_func) mailimap_extension_data_free, NULL); + clist_free(session->imap_response_info->rsp_extension_list); + session->imap_response_info->rsp_extension_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + /* if there is no data to be returned, return MAILIMAP_ERROR_EXTENSION */ + if (* result == NULL) + return MAILIMAP_ERROR_EXTENSION; + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXTENSION; + } +} + +LIBETPAN_EXPORT +int mailimap_acl_myrights(mailimap * session, + const char * mailbox, + struct mailimap_acl_myrights_data ** result) +{ + struct mailimap_response * response; + struct mailimap_extension_data * ext_data; + clistiter * cur; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_myrights_send(session->imap_stream, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = NULL; + + /* in rsp_extension_list there is at most one myrights_data */ + for (cur = clist_begin(session->imap_response_info->rsp_extension_list); + cur != NULL; cur = clist_next(cur)) { + ext_data = (struct mailimap_extension_data *) clist_content(cur); + if ( + ext_data->ext_extension->ext_id == MAILIMAP_EXTENSION_ACL && + ext_data->ext_type == MAILIMAP_ACL_TYPE_MYRIGHTS_DATA) { + * result = (struct mailimap_acl_myrights_data *)ext_data->ext_data; + /* remove the element from rsp_extension_list */ + clist_delete(session->imap_response_info->rsp_extension_list, cur); + + break; + } + } + + clist_foreach(session->imap_response_info->rsp_extension_list, + (clist_func) mailimap_extension_data_free, NULL); + clist_free(session->imap_response_info->rsp_extension_list); + session->imap_response_info->rsp_extension_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + /* if there is no data to be returned, return MAILIMAP_ERROR_EXTENSION */ + if (* result == NULL) + return MAILIMAP_ERROR_EXTENSION; + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXTENSION; + } +} + +LIBETPAN_EXPORT +int mailimap_has_acl(mailimap * session) +{ + return mailimap_has_extension(session, "ACL"); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/acl.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/acl.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,164 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + TODO: parse extension to capability as defined in [rfc4314]. + capability =/ rights-capa + + This should actually be automatically parsed by parse_capability_data, + so maybe it's sufficient to code a higher-level (not mailimap) function + that returns a list of extra-rights as defined in rights-capa. +*/ + +#ifndef ACL_H + +#define ACL_H + +#include <libetpan/mailimap_extension.h> +#include <libetpan/acl_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_acl; + +/* + mailimap_acl_setacl() + + This will set access for an identifier on the mailbox specified. + + @param session the IMAP session + @param mailbox the mailbox to modify + @param identifier the identifier to set access-rights for + @param mod_rights the modification to make to the rights + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_acl_setacl(mailimap * session, + const char * mailbox, + const char * identifier, + const char * mod_rights); + +/* + mailimap_acl_deleteacl() + + This will remove the acl on the mailbox for the identifier specified. + + @param session the IMAP session + @param mailbox the mailbox to modify + @param identifier the identifier to remove acl for + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_acl_deleteacl(mailimap * session, + const char * mailbox, + const char * identifier); + +/* + mailimap_acl_getacl() + + This will get a list of acls for the mailbox + + @param session the IMAP session + @param mailbox the mailbox to get the acls for + @param result this will store a clist of (struct mailimap_acl_acl_data *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_acl_getacl(mailimap * session, + const char * mailbox, + clist ** result); + +/* + mailimap_acl_listrights() + + The LISTRIGHTS command takes a mailbox name and an identifier and + returns information about what rights can be granted to the + identifier in the ACL for the mailbox. + + @param session the IMAP session + @param mailbox the mailbox to get the acls for + @param identifier the identifier to query the acls for + @param result this will store a (struct mailimap_acl_listrights_data *) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_acl_listrights(mailimap * session, + const char * mailbox, + const char * identifier, + struct mailimap_acl_listrights_data ** result); + +/* + mailimap_acl_myrights() + + This will list the rights for the querying user on the mailbox + + @param session the IMAP session + @param mailbox the mailbox to get the acls for + @param result this will store a (struct mailimap_acl_myrights_data *) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_acl_myrights(mailimap * session, + const char * mailbox, + struct mailimap_acl_myrights_data ** result); + +LIBETPAN_EXPORT +int mailimap_has_acl(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_parser.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_parser.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,456 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "acl_parser.h" +#include "mailimap_keywords.h" +#include "mailimap_extension.h" +#include "acl.h" + +#include <stdlib.h> + +int +mailimap_acl_acl_data_parse(mailstream * fd, MMAPString *buffer, + size_t * index, + struct mailimap_acl_acl_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * mailbox; + clist * ir_list; + struct mailimap_acl_acl_data * acl_data; + int r; + int res; + + cur_token = * index; + + mailbox = NULL; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "ACL"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_mailbox_parse(fd, buffer, &cur_token, &mailbox, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, + &cur_token, &ir_list, + (mailimap_struct_parser * ) + mailimap_acl_identifier_rights_parse, + (mailimap_struct_destructor * ) + mailimap_acl_identifier_rights_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + acl_data = mailimap_acl_acl_data_new(mailbox, + ir_list); + if (acl_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto ir_list_free; + } + + * result = acl_data; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + ir_list_free: + if (ir_list != NULL) { + clist_foreach(ir_list, + (clist_func) mailimap_acl_identifier_rights_free, NULL); + clist_free(ir_list); + } + mailbox_free: + mailimap_mailbox_free(mailbox); + err: + return res; +} + +int +mailimap_acl_listrights_data_parse(mailstream * fd, MMAPString *buffer, + size_t * index, + struct mailimap_acl_listrights_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * mailbox; + char * identifier; + clist * rights_list; + struct mailimap_acl_listrights_data * lr_data; + int r; + int res; + + cur_token = * index; + + mailbox = NULL; /* XXX - removes a gcc warning */ + identifier = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "LISTRIGHTS"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_mailbox_parse(fd, buffer, &cur_token, &mailbox, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + r = mailimap_acl_identifier_parse(fd, buffer, &cur_token, &identifier, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto identifier_free; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, + &cur_token, &rights_list, + (mailimap_struct_parser * ) + mailimap_acl_rights_parse, + (mailimap_struct_destructor * ) + mailimap_acl_rights_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto identifier_free; + } + + lr_data = mailimap_acl_listrights_data_new(mailbox, identifier, + rights_list); + if (lr_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto rights_list_free; + } + + * result = lr_data; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + rights_list_free: + if (rights_list != NULL) { + clist_foreach(rights_list, + (clist_func) mailimap_acl_rights_free, NULL); + clist_free(rights_list); + } + identifier_free: + mailimap_acl_identifier_free(identifier); + mailbox_free: + mailimap_mailbox_free(mailbox); + err: + return res; +} + +int +mailimap_acl_myrights_data_parse(mailstream * fd, MMAPString *buffer, + size_t * index, + struct mailimap_acl_myrights_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * mailbox; + char * rights; + struct mailimap_acl_myrights_data * mr_data; + int r; + int res; + + cur_token = * index; + + mailbox = NULL; /* XXX - removes a gcc warning */ + rights = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "MYRIGHTS"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_mailbox_parse(fd, buffer, &cur_token, &mailbox, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + r = mailimap_acl_rights_parse(fd, buffer, &cur_token, &rights, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + mr_data = mailimap_acl_myrights_data_new(mailbox, rights); + if (mr_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto rights_free; + } + + * result = mr_data; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + rights_free: + mailimap_acl_rights_free(rights); + mailbox_free: + mailimap_mailbox_free(mailbox); + err: + return res; +} + +int +mailimap_acl_identifier_rights_parse(mailstream * fd, + MMAPString *buffer, size_t * index, + struct mailimap_acl_identifier_rights ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * identifier; + char * rights; + struct mailimap_acl_identifier_rights * id_rights; + int r; + int res; + + cur_token = * index; + + identifier = NULL; /* XXX - removes a gcc warning */ + rights = NULL; + + r = mailimap_acl_identifier_parse(fd, buffer, &cur_token, &identifier, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto identifier_free; + } + + r = mailimap_acl_rights_parse(fd, buffer, &cur_token, &rights, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto identifier_free; + } + + id_rights = mailimap_acl_identifier_rights_new(identifier, rights); + if (id_rights == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto rights_free; + } + + * result = id_rights; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + rights_free: + mailimap_acl_rights_free(rights); + identifier_free: + mailimap_acl_identifier_free(identifier); + err: + return res; +} + +int +mailimap_acl_identifier_parse(mailstream * fd, + MMAPString *buffer, size_t * index, + char ** result, size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_astring_parse(fd, buffer, index, result, + progr_rate, progr_fun); +} + +int mailimap_acl_rights_parse(mailstream * fd, + MMAPString *buffer, size_t * index, + char ** result, size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_astring_parse(fd, buffer, index, result, + progr_rate, progr_fun); +} + +/* + this is the extension's initial parser. it switches on calling_parser + and calls the corresponding actual parser. acl extends + imap as follows: + mailbox-data =/ acl-data / listrights-data / myrights-data + ;;mailbox-data is defined in [IMAP4] + capability =/ rights-capa + ;;capability is defined in [IMAP4] + + the extension to capability is omitted so far. +*/ + +int mailimap_acl_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, size_t * index, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + int res; + + struct mailimap_acl_acl_data * acl_data; + struct mailimap_acl_listrights_data * lr_data; + struct mailimap_acl_myrights_data * mr_data; + + void * data; + + int type; + + switch (calling_parser) + { + case MAILIMAP_EXTENDED_PARSER_MAILBOX_DATA: + r = mailimap_acl_acl_data_parse(fd, buffer, index, + &acl_data, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + type = MAILIMAP_ACL_TYPE_ACL_DATA; + data = acl_data; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_acl_listrights_data_parse(fd, buffer, index, + &lr_data, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + type = MAILIMAP_ACL_TYPE_LISTRIGHTS_DATA; + data = lr_data; + } + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_acl_myrights_data_parse(fd, buffer, index, + &mr_data, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + type = MAILIMAP_ACL_TYPE_MYRIGHTS_DATA; + data = mr_data; + } + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + * result = mailimap_extension_data_new(&mailimap_extension_acl, + type, data); + if (result == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto data_free; + } + break; + default: + /* return a MAILIMAP_ERROR_PARSE if the extension + doesn't extend calling_parser. */ + return MAILIMAP_ERROR_PARSE; + break; + } + + return MAILIMAP_NO_ERROR; + + data_free: + if (acl_data != NULL) + mailimap_acl_acl_data_free(acl_data); + if (lr_data != NULL) + mailimap_acl_listrights_data_free(lr_data); + if (mr_data != NULL) + mailimap_acl_myrights_data_free(mr_data); + err: + return res; +} + Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_parser.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_parser.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,92 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ACL_PARSER_H + +#define ACL_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_parser.h" +#include "acl_types.h" + +int +mailimap_acl_acl_data_parse(mailstream * fd, MMAPString *buffer, + size_t * index, + struct mailimap_acl_acl_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_acl_listrights_data_parse(mailstream * fd, MMAPString *buffer, + size_t * index, + struct mailimap_acl_listrights_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_acl_myrights_data_parse(mailstream * fd, MMAPString *buffer, + size_t * index, + struct mailimap_acl_myrights_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_acl_identifier_rights_parse(mailstream * fd, + MMAPString *buffer, size_t * index, + struct mailimap_acl_identifier_rights ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_acl_identifier_parse(mailstream * fd, + MMAPString *buffer, size_t * index, + char ** result, size_t progr_rate, + progress_function * progr_fun); + +int mailimap_acl_rights_parse(mailstream * fd, + MMAPString *buffer, size_t * index, + char ** result, size_t progr_rate, + progress_function * progr_fun); + +int mailimap_acl_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, size_t * index, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_sender.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_sender.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,185 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimap_sender.h" +#include "acl_types.h" + +static int mailimap_acl_identifier_send(mailstream * fd, + const char * identifier) +{ + return mailimap_astring_send(fd, identifier); +} + +static int mailimap_acl_mod_rights_send(mailstream * fd, + const char * mod_rights) +{ + return mailimap_astring_send(fd, mod_rights); +} + +int mailimap_acl_setacl_send(mailstream * fd, + const char * mailbox, + const char * identifier, + const char * mod_rights) +{ + int r; + + r = mailimap_token_send(fd, "SETACL"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_identifier_send(fd, identifier); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_mod_rights_send(fd, mod_rights); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_acl_deleteacl_send(mailstream * fd, + const char * mailbox, + const char * identifier) +{ + int r; + + r = mailimap_token_send(fd, "DELETEACL"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_identifier_send(fd, identifier); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_acl_getacl_send(mailstream * fd, + const char * mailbox) +{ + int r; + + r = mailimap_token_send(fd, "GETACL"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_acl_listrights_send(mailstream * fd, + const char * mailbox, + const char * identifier) +{ + int r; + + r = mailimap_token_send(fd, "LISTRIGHTS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_acl_identifier_send(fd, identifier); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_acl_myrights_send(mailstream * fd, + const char * mailbox) +{ + int r; + + r = mailimap_token_send(fd, "MYRIGHTS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_sender.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_sender.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,66 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ACL_SENDER_H + +#define ACL_SENDER_H + +#include "mailimap_sender.h" +#include "acl_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mailimap_acl_setacl_send(mailstream * fd, + const char * mailbox, + const char * identifier, + const char * mod_rights); + +int mailimap_acl_deleteacl_send(mailstream * fd, + const char * mailbox, + const char * identifier); + +int mailimap_acl_getacl_send(mailstream * fd, + const char * mailbox); + +int mailimap_acl_listrights_send(mailstream * fd, + const char * mailbox, + const char * identifier); + +int mailimap_acl_myrights_send(mailstream * fd, + const char * mailbox); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_types.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_types.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,176 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimap_types.h" +#include "acl_types.h" +#include "mailimap_extension.h" + +#include <stdlib.h> +#include <string.h> + +void mailimap_acl_identifier_free(char * identifier) +{ + mailimap_astring_free(identifier); +} + +void mailimap_acl_rights_free(char * rights) +{ + mailimap_astring_free(rights); +} + +struct mailimap_acl_identifier_rights * +mailimap_acl_identifier_rights_new(char * identifier, char * rights) +{ + struct mailimap_acl_identifier_rights * id_rights; + + id_rights = malloc(sizeof(* id_rights)); + if (id_rights == NULL) + return NULL; + + id_rights->identifer = identifier; + id_rights->rights = rights; + + return id_rights; +} + +void mailimap_acl_identifier_rights_free( + struct mailimap_acl_identifier_rights * id_rights) +{ + mailimap_acl_identifier_free(id_rights->identifer); + mailimap_acl_rights_free(id_rights->rights); + + free(id_rights); +} + +struct mailimap_acl_acl_data * +mailimap_acl_acl_data_new(char * mailbox, clist * idrights_list) +{ + struct mailimap_acl_acl_data * acl_data; + + acl_data = malloc(sizeof(* acl_data)); + if (acl_data == NULL) + return NULL; + + acl_data->mailbox = mailbox; + acl_data->idrights_list = idrights_list; + + return acl_data; +} + +LIBETPAN_EXPORT +void mailimap_acl_acl_data_free(struct + mailimap_acl_acl_data * acl_data) +{ + mailimap_mailbox_free(acl_data->mailbox); + clist_foreach(acl_data->idrights_list, + (clist_func) mailimap_acl_identifier_rights_free, NULL); + clist_free(acl_data->idrights_list); + free(acl_data); +} + +struct mailimap_acl_listrights_data * +mailimap_acl_listrights_data_new(char * mailbox, + char * identifier, clist * rights_list) +{ + struct mailimap_acl_listrights_data * lr_data; + + lr_data = malloc(sizeof(* lr_data)); + if (lr_data == NULL) + return NULL; + + lr_data->mailbox = mailbox; + lr_data->identifier = identifier; + lr_data->rights_list = rights_list; + + return lr_data; +} + +LIBETPAN_EXPORT +void mailimap_acl_listrights_data_free(struct + mailimap_acl_listrights_data * lr_data) +{ + mailimap_mailbox_free(lr_data->mailbox); + mailimap_acl_identifier_free(lr_data->identifier); + clist_foreach(lr_data->rights_list, + (clist_func) mailimap_acl_rights_free, NULL); + clist_free(lr_data->rights_list); + free(lr_data); +} + +struct mailimap_acl_myrights_data * +mailimap_acl_myrights_data_new(char * mailbox, char * rights) +{ + struct mailimap_acl_myrights_data * mr_data; + + mr_data = malloc(sizeof(* mr_data)); + if (mr_data == NULL) + return NULL; + + mr_data->mailbox = mailbox; + mr_data->rights = rights; + + return mr_data; +} + +LIBETPAN_EXPORT +void mailimap_acl_myrights_data_free(struct + mailimap_acl_myrights_data * mr_data) +{ + mailimap_mailbox_free(mr_data->mailbox); + mailimap_acl_rights_free(mr_data->rights); + free(mr_data); +} + +void +mailimap_acl_free(struct mailimap_extension_data * ext_data) +{ + if (ext_data == NULL) + return; + + switch (ext_data->ext_type) + { + case MAILIMAP_ACL_TYPE_ACL_DATA: + mailimap_acl_acl_data_free(ext_data->ext_data); + break; + case MAILIMAP_ACL_TYPE_LISTRIGHTS_DATA: + mailimap_acl_listrights_data_free(ext_data->ext_data); + break; + case MAILIMAP_ACL_TYPE_MYRIGHTS_DATA: + mailimap_acl_myrights_data_free(ext_data->ext_data); + break; + } + + free (ext_data); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/acl_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,169 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ACL_TYPES_H + +#define ACL_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/libetpan-config.h> +#include <libetpan/mailstream.h> +#include <libetpan/clist.h> + +/* + ACL grammar + see [rfc4314] for further information + + LOWER-ALPHA = %x61-7A ;; a-z + + acl-data = "ACL" SP mailbox *(SP identifier SP + rights) + + capability =/ rights-capa + ;;capability is defined in [IMAP4] + + command-auth =/ setacl / deleteacl / getacl / + listrights / myrights + ;;command-auth is defined in [IMAP4] + + deleteacl = "DELETEACL" SP mailbox SP identifier + + getacl = "GETACL" SP mailbox + + identifier = astring + + listrights = "LISTRIGHTS" SP mailbox SP identifier + + listrights-data = "LISTRIGHTS" SP mailbox SP identifier + SP rights *(SP rights) + + mailbox-data =/ acl-data / listrights-data / myrights-data + ;;mailbox-data is defined in [IMAP4] + + mod-rights = astring + ;; +rights to add, -rights to remove + ;; rights to replace + + myrights = "MYRIGHTS" SP mailbox + + myrights-data = "MYRIGHTS" SP mailbox SP rights + + new-rights = 1*LOWER-ALPHA + ;; MUST include "t", "e", "x", and "k". + ;; MUST NOT include standard rights listed + ;; in section 2.2 + + rights = astring + ;; only lowercase ASCII letters and digits + ;; are allowed. + + rights-capa = "RIGHTS=" new-rights + ;; RIGHTS=... capability + + setacl = "SETACL" SP mailbox SP identifier + SP mod-rights +*/ + +/* + only need to recognize types that can be "embedded" into main + IMAPrev1 types. +*/ +enum { + MAILIMAP_ACL_TYPE_ACL_DATA, /* child of mailbox-data */ + MAILIMAP_ACL_TYPE_LISTRIGHTS_DATA, /* child of mailbox-data */ + MAILIMAP_ACL_TYPE_MYRIGHTS_DATA, /* child of mailbox-data */ +}; + +void mailimap_acl_identifier_free(char * identifier); + +void mailimap_acl_rights_free(char * rights); + +struct mailimap_acl_identifier_rights { + char * identifer; + char * rights; +}; + +struct mailimap_acl_identifier_rights * +mailimap_acl_identifier_rights_new(char * identifier, char * rights); + +void mailimap_acl_identifier_rights_free( + struct mailimap_acl_identifier_rights * id_rights); + +struct mailimap_acl_acl_data { + char * mailbox; + clist * idrights_list; + /* list of (struct mailimap_acl_identifier_rights *) */ +}; + +struct mailimap_acl_acl_data * +mailimap_acl_acl_data_new(char * mailbox, clist * idrights_list); + +LIBETPAN_EXPORT +void mailimap_acl_acl_data_free(struct + mailimap_acl_acl_data * acl_data); + +struct mailimap_acl_listrights_data { + char * mailbox; + char * identifier; + clist * rights_list; /* list of (char *) */ +}; + +struct mailimap_acl_listrights_data * +mailimap_acl_listrights_data_new(char * mailbox, + char * identifier, clist * rights_list); + +LIBETPAN_EXPORT +void mailimap_acl_listrights_data_free(struct + mailimap_acl_listrights_data * listrights_data); + +struct mailimap_acl_myrights_data { + char * mailbox; + char * rights; +}; + +struct mailimap_acl_myrights_data * +mailimap_acl_myrights_data_new(char * mailbox, char * rights); + +LIBETPAN_EXPORT +void mailimap_acl_myrights_data_free(struct + mailimap_acl_myrights_data * myrights_data); + +void +mailimap_acl_free(struct mailimap_extension_data * ext_data); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,215 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimap.h" +#include "mailimap_extension.h" +#include "annotatemore.h" +#include "annotatemore_types.h" +#include "annotatemore_parser.h" +#include "annotatemore_sender.h" + +#include <stdlib.h> + +LIBETPAN_EXPORT +struct mailimap_extension_api mailimap_extension_annotatemore = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* name */ "ANNOTATEMORE", + /* extension_id */ MAILIMAP_EXTENSION_ANNOTATEMORE, + /* parser */ mailimap_annotatemore_parse, + /* free */ mailimap_annotatemore_free, +#else + .name = "ANNOTATEMORE", + .extension_id = MAILIMAP_EXTENSION_ANNOTATEMORE, + .parser = mailimap_annotatemore_parse, + .free = mailimap_annotatemore_free, +#endif +}; + +/* + this is one of the imap commands annotatemore adds. setannotation is + yet to be implemented. +*/ +LIBETPAN_EXPORT +int mailimap_annotatemore_getannotation(mailimap * session, + const char * list_mb, + struct mailimap_annotatemore_entry_match_list * entries, + struct mailimap_annotatemore_attrib_match_list * attribs, + clist ** result) +{ + struct mailimap_response * response; + struct mailimap_extension_data * ext_data; + clistiter * cur; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_annotatemore_getannotation_send(session->imap_stream, + list_mb, entries, attribs); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = clist_new(); + if (* result == NULL) + return MAILIMAP_ERROR_MEMORY; + + /* copy all annotate_data to the result-list */ + for (cur = clist_begin(session->imap_response_info->rsp_extension_list); + cur != NULL; cur = clist_next(cur)) { + ext_data = (struct mailimap_extension_data *) clist_content(cur); + if ( + ext_data->ext_extension->ext_id == MAILIMAP_EXTENSION_ANNOTATEMORE && + ext_data->ext_type == MAILIMAP_ANNOTATEMORE_TYPE_ANNOTATE_DATA) { + r = clist_append((* result), ext_data->ext_data); + if (r != 0) + return MAILIMAP_ERROR_MEMORY; + + ext_data->ext_data = NULL; + ext_data->ext_type = -1; + } + } + + clist_foreach(session->imap_response_info->rsp_extension_list, + (clist_func) mailimap_extension_data_free, NULL); + clist_free(session->imap_response_info->rsp_extension_list); + session->imap_response_info->rsp_extension_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXTENSION; + } +} + +LIBETPAN_EXPORT +int mailimap_annotatemore_setannotation(mailimap * session, + const char * list_mb, + struct mailimap_annotatemore_entry_att_list * en_att, + int * result) +{ + struct mailimap_response * response; + int r; + int error_code; + clistiter * cur; + struct mailimap_extension_data * ext_data; + + if (session->imap_state != MAILIMAP_STATE_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_annotatemore_setannotation_send(session->imap_stream, + list_mb, en_att); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + break; + case MAILIMAP_RESP_COND_STATE_NO: + * result = MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_UNSPECIFIED; + if (session->imap_response_info->rsp_extension_list != NULL) { + for (cur = clist_begin(session->imap_response_info->rsp_extension_list); + cur != NULL; cur = clist_next(cur)) { + ext_data = clist_content(cur); + if ((ext_data->ext_extension->ext_id == + MAILIMAP_EXTENSION_ANNOTATEMORE) && + (ext_data->ext_type == + MAILIMAP_ANNOTATEMORE_TYPE_RESP_TEXT_CODE)) + { + * result = * ((int *)ext_data->ext_data); + } + } + } + return MAILIMAP_ERROR_EXTENSION; + break; + default: + * result = MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_UNSPECIFIED; + return MAILIMAP_ERROR_EXTENSION; + break; + } +} + +LIBETPAN_EXPORT +int mailimap_has_annotatemore(mailimap * session) +{ + return mailimap_has_extension(session, "ANNOTATEMORE"); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,102 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ANNOTATEMORE_H + +#define ANNOTATEMORE_H + +#include <libetpan/mailimap_extension.h> +#include <libetpan/annotatemore_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_annotatemore; + +/* + mailimap_annotatemore_getannotation() + + This function will get annotations from given mailboxes or the server. + + @param session the IMAP session + @param list_mb mailbox name with possible wildcard, + empty string implies server annotation + @param entries entry specifier with possible wildcards + @param attribs attribute specifier with possible wildcards + @param result This will store a clist of (struct mailimap_annotate_data *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + +*/ + +LIBETPAN_EXPORT +int mailimap_annotatemore_getannotation(mailimap * session, + const char * list_mb, + struct mailimap_annotatemore_entry_match_list * entries, + struct mailimap_annotatemore_attrib_match_list * attribs, + clist ** result); + +/* + mailimap_annotatemore_setannotation() + + This function will set annotations on given mailboxes or the server. + + @param session the IMAP session + @param list_mb mailbox name with possible wildcard, + empty string implies server annotation + @param en_att a list of entries/attributes to set + @param result if return is MAILIMAP_ERROR_EXTENSION result + is MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOBIG or + MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOMANY for + extra information about the error. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_annotatemore_setannotation(mailimap * session, + const char * list_mb, + struct mailimap_annotatemore_entry_att_list * en_att, + int * result); + +LIBETPAN_EXPORT +int mailimap_has_annotatemore(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_parser.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_parser.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,461 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "annotatemore_parser.h" +#include "mailimap_keywords.h" +#include "mailimap_extension.h" +#include "annotatemore.h" + +#include <stdlib.h> + +int +mailimap_annotatemore_annotate_data_parse(mailstream * fd, MMAPString *buffer, + size_t * index, struct mailimap_annotatemore_annotate_data ** result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + char * mailbox; + struct mailimap_annotatemore_entry_list * entry_list; + struct mailimap_annotatemore_annotate_data * annotate_data; + int r; + int res; + + cur_token = * index; + + mailbox = NULL; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "ANNOTATION"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_mailbox_parse(fd, buffer, &cur_token, &mailbox, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + r = mailimap_annotatemore_entry_list_parse(fd, buffer, &cur_token, + &entry_list, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox_free; + } + + annotate_data = mailimap_annotatemore_annotate_data_new(mailbox, + entry_list); + if (annotate_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto entry_list_free; + } + + * result = annotate_data; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + entry_list_free: + mailimap_annotatemore_entry_list_free(entry_list); + mailbox_free: + mailimap_mailbox_free(mailbox); + err: + return res; +} + +int +mailimap_annotatemore_entry_list_parse(mailstream * fd, MMAPString *buffer, + size_t * index, + struct mailimap_annotatemore_entry_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * en_att_list; + clist * en_list; + int type; + struct mailimap_annotatemore_entry_list * entry_list; + int r; + int res; + + cur_token = * index; + + /* XXX - removes a gcc warning */ + type = MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ERROR; + en_list = NULL; + en_att_list = NULL; + + r = mailimap_struct_spaced_list_parse(fd, buffer, + &cur_token, &en_att_list, + (mailimap_struct_parser * ) + mailimap_annotatemore_entry_att_parse, + (mailimap_struct_destructor * ) + mailimap_annotatemore_entry_att_free, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_ATT_LIST; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, + &cur_token, &en_list, + (mailimap_struct_parser * ) + mailimap_annotatemore_entry_parse, + (mailimap_struct_destructor * ) + mailimap_annotatemore_entry_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto en_list_free; + } + + type = MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_LIST; + } + + entry_list = mailimap_annotatemore_entry_list_new(type, en_att_list, en_list); + if (entry_list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto list_free; + } + + * result = entry_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + list_free: + if (en_att_list != NULL) { + clist_foreach(en_att_list, + (clist_func) mailimap_annotatemore_entry_att_free, NULL); + clist_free(en_att_list); + } + en_list_free: + if (en_list != NULL) { + clist_foreach(en_list, + (clist_func) mailimap_annotatemore_entry_free, NULL); + clist_free(en_list); + } + err: + return res; +} + +int +mailimap_annotatemore_entry_att_parse(mailstream * fd, MMAPString *buffer, + size_t * index, + struct mailimap_annotatemore_entry_att ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * entry; + clist * list; + struct mailimap_annotatemore_entry_att * entry_att; + int r; + int res; + + cur_token = * index; + entry = NULL; + + r = mailimap_annotatemore_entry_parse(fd, buffer, &cur_token, &entry, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto entry_free; + } + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto entry_free; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, + &cur_token, &list, + (mailimap_struct_parser * ) + mailimap_annotatemore_att_value_parse, + (mailimap_struct_destructor * ) + mailimap_annotatemore_att_value_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto entry_free; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto list_free; + } + + entry_att = mailimap_annotatemore_entry_att_new(entry, list); + if (entry_att == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto list_free; + } + + * result = entry_att; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + list_free: + clist_foreach(list, + (clist_func) mailimap_annotatemore_att_value_free, NULL); + clist_free(list); + entry_free: + mailimap_annotatemore_entry_free(entry); + err: + return res; +} + +int +mailimap_annotatemore_att_value_parse(mailstream * fd, MMAPString *buffer, + size_t * index, + struct mailimap_annotatemore_att_value ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * attrib; + char * value; + struct mailimap_annotatemore_att_value * att_value; + int r; + int res; + + cur_token = * index; + attrib = NULL; + value = NULL; + + r = mailimap_annotatemore_attrib_parse(fd, buffer, &cur_token, &attrib, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto attrib_free; + } + + r = mailimap_annotatemore_value_parse(fd, buffer, &cur_token, &value, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto attrib_free; + } + + att_value = mailimap_annotatemore_att_value_new(attrib, value); + if (att_value == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto value_free; + } + + * result = att_value; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + value_free: + mailimap_annotatemore_value_free(value); + attrib_free: + mailimap_annotatemore_attrib_free(attrib); + err: + return res; +} + +int +mailimap_annotatemore_attrib_parse(mailstream * fd, MMAPString *buffer, + size_t * index, char ** result, + size_t progr_rate, progress_function * progr_fun) +{ + return mailimap_string_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +int +mailimap_annotatemore_value_parse(mailstream * fd, MMAPString *buffer, + size_t * index, char ** result, + size_t progr_rate, progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +int +mailimap_annotatemore_entry_parse(mailstream * fd, MMAPString *buffer, + size_t * index, char ** result, + size_t progr_rate, progress_function * progr_fun) +{ + return mailimap_string_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +int +mailimap_annotatemore_text_code_annotatemore_parse(mailstream * fd, + MMAPString *buffer, size_t * index, int * result, + size_t progr_rate, progress_function * progr_fun) +{ + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "ANNOTATEMORE"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "TOOBIG"); + if (r == MAILIMAP_NO_ERROR) { + * result = MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOBIG; + } else { + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "TOOMANY"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + * result = MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOMANY; + } + + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + err: + return res; +} + + +/* + this is the extension's initial parser. it switches on calling_parser + and calls the corresponding actual parser. annotatemore extends + imap as follows: + response-data /= "*" SP annotate-data CRLF + ; adds to original IMAP data responses + + resp-text-code =/ "ANNOTATEMORE" SP "TOOBIG" / + "ANNOTATEMORE" SP "TOOMANY" + ; new response codes for SETANNOTATION failures +*/ +int mailimap_annotatemore_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, size_t * index, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + + struct mailimap_annotatemore_annotate_data * an_data; + int resp_text_code; + + switch (calling_parser) + { + case MAILIMAP_EXTENDED_PARSER_RESPONSE_DATA: + r = mailimap_annotatemore_annotate_data_parse(fd, buffer, index, + &an_data, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + * result = mailimap_extension_data_new(&mailimap_extension_annotatemore, + MAILIMAP_ANNOTATEMORE_TYPE_ANNOTATE_DATA, an_data); + if (result == NULL) { + mailimap_annotatemore_annotate_data_free(an_data); + return MAILIMAP_ERROR_MEMORY; + } + break; + case MAILIMAP_EXTENDED_PARSER_RESP_TEXT_CODE: + r = mailimap_annotatemore_text_code_annotatemore_parse(fd, buffer, index, + &resp_text_code, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + * result = mailimap_extension_data_new(&mailimap_extension_annotatemore, + MAILIMAP_ANNOTATEMORE_TYPE_RESP_TEXT_CODE, &resp_text_code); + if (result == NULL) + return MAILIMAP_ERROR_MEMORY; + break; + default: + /* return a MAILIMAP_ERROR_PARSE if the extension + doesn't extend calling_parser. */ + return MAILIMAP_ERROR_PARSE; + break; + } + + return MAILIMAP_NO_ERROR; +} + Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_parser.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_parser.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,104 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ANNOTATEMORE_PARSER_H + +#define ANNOTATEMORE_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_parser.h" +#include "annotatemore_types.h" + +int +mailimap_annotatemore_annotate_data_parse(mailstream * fd, MMAPString *buffer, + size_t * index, + struct mailimap_annotatemore_annotate_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_entry_list_parse(mailstream * fd, MMAPString *buffer, + size_t * index, + struct mailimap_annotatemore_entry_list ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_entry_att_parse(mailstream * fd, MMAPString *buffer, + size_t * index, + struct mailimap_annotatemore_entry_att ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_att_value_parse(mailstream * fd, MMAPString *buffer, + size_t * index, + struct mailimap_annotatemore_att_value ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_attrib_parse(mailstream * fd, MMAPString *buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_value_parse(mailstream * fd, MMAPString *buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_entry_parse(mailstream * fd, MMAPString *buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_annotatemore_text_code_annotatemore_parse(mailstream * fd, + MMAPString *buffer, size_t * index, int * result, + size_t progr_rate, progress_function * progr_fun); + +int mailimap_annotatemore_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, size_t * index, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_sender.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_sender.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,213 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimap_sender.h" +#include "annotatemore_types.h" + +static int annotatemore_string_send(mailstream * fd, const char * str) +{ + return mailimap_quoted_send(fd, str); +} + +static int +annotatemore_entry_match_list_send(mailstream * fd, + struct mailimap_annotatemore_entry_match_list * em_list) +{ + return mailimap_struct_spaced_list_send(fd, em_list->entry_match_list, + (mailimap_struct_sender *) annotatemore_string_send); +} + +static int +annotatemore_attrib_match_list_send(mailstream * fd, + struct mailimap_annotatemore_attrib_match_list * am_list) +{ + /* TODO actually attrib-match is defined as string, not astring */ + return mailimap_struct_spaced_list_send(fd, am_list->attrib_match_list, + (mailimap_struct_sender *) annotatemore_string_send); +} + +int mailimap_annotatemore_getannotation_send(mailstream * fd, + const char * list_mb, + struct mailimap_annotatemore_entry_match_list * entries, + struct mailimap_annotatemore_attrib_match_list * attribs) +{ + int r; + + r = mailimap_token_send(fd, "GETANNOTATION"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_mailbox_send(fd, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '('); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = annotatemore_entry_match_list_send(fd, entries); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ')'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '('); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = annotatemore_attrib_match_list_send(fd, attribs); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ')'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int +annotatemore_att_value_send(mailstream * fd, + struct mailimap_annotatemore_att_value * att_value) +{ + int r; + + r = annotatemore_string_send(fd, att_value->attrib); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = annotatemore_string_send(fd, att_value->value); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int +annotatemore_entry_att_send(mailstream * fd, + struct mailimap_annotatemore_entry_att * en_att) +{ + int r; + + r = annotatemore_string_send(fd, en_att->entry); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '('); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_send(fd, en_att->att_value_list, + (mailimap_struct_sender *) annotatemore_att_value_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ')'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int +annotatemore_entry_att_list_send(mailstream * fd, + struct mailimap_annotatemore_entry_att_list * en_list) +{ + return mailimap_struct_spaced_list_send(fd, en_list->entry_att_list, + (mailimap_struct_sender *) annotatemore_entry_att_send); +} + +int mailimap_annotatemore_setannotation_send(mailstream * fd, + const char * list_mb, + struct mailimap_annotatemore_entry_att_list * en_list) +{ + int r; + + r = mailimap_token_send(fd, "SETANNOTATION"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_mailbox_send(fd, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (en_list->entry_att_list->count > 1) { + r = mailimap_char_send(fd, '('); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = annotatemore_entry_att_list_send(fd, en_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (en_list->entry_att_list->count > 1) { + r = mailimap_char_send(fd, ')'); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + return MAILIMAP_NO_ERROR; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_sender.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_sender.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ANNOTATEMORE_SENDER_H + +#define ANNOTATEMORE_SENDER_H + +#include "mailimap_sender.h" +#include "annotatemore_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int mailimap_annotatemore_getannotation_send(mailstream * fd, + const char * list_mb, + struct mailimap_annotatemore_entry_match_list * entries, + struct mailimap_annotatemore_attrib_match_list * attribs); + +int mailimap_annotatemore_setannotation_send(mailstream * fd, + const char * list_mb, + struct mailimap_annotatemore_entry_att_list * en_att); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_types.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_types.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,395 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimap_types.h" +#include "annotatemore_types.h" +#include "mailimap_extension.h" + +#include <stdlib.h> +#include <string.h> + +void mailimap_annotatemore_attrib_free(char * attrib) +{ + mailimap_string_free(attrib); +} + +void mailimap_annotatemore_value_free(char * value) +{ + mailimap_nstring_free(value); +} + +void mailimap_annotatemore_entry_free(char * entry) +{ + mailimap_string_free(entry); +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_att_value * +mailimap_annotatemore_att_value_new(char * attrib, char * value) +{ + struct mailimap_annotatemore_att_value * att_value; + + att_value = malloc(sizeof(* att_value)); + if (att_value == NULL) + return NULL; + + att_value->attrib = attrib; + att_value->value = value; + + return att_value; +} + +void mailimap_annotatemore_att_value_free(struct + mailimap_annotatemore_att_value * att_value) +{ + mailimap_annotatemore_attrib_free(att_value->attrib); + mailimap_annotatemore_value_free(att_value->value); + + free(att_value); +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att * +mailimap_annotatemore_entry_att_new(char * entry, clist * list) +{ + struct mailimap_annotatemore_entry_att * entry_att; + + entry_att = malloc(sizeof(* entry_att)); + if (entry_att == NULL) + return NULL; + + entry_att->entry = entry; + entry_att->att_value_list = list; + + return entry_att; +} + +LIBETPAN_EXPORT +void mailimap_annotatemore_entry_att_free(struct + mailimap_annotatemore_entry_att * en_att) +{ + mailimap_annotatemore_entry_free(en_att->entry); + clist_foreach(en_att->att_value_list, + (clist_func) mailimap_annotatemore_att_value_free, NULL); + clist_free(en_att->att_value_list); + free(en_att); +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att * +mailimap_annotatemore_entry_att_new_empty(char * entry) +{ + struct mailimap_annotatemore_entry_att * entry_att; + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + entry_att = mailimap_annotatemore_entry_att_new(entry, list); + if (entry_att == NULL) + return NULL; + + return entry_att; +} + +LIBETPAN_EXPORT +int mailimap_annotatemore_entry_att_add(struct + mailimap_annotatemore_entry_att * en_att, + struct mailimap_annotatemore_att_value * at_value) +{ + int r; + + if (en_att->att_value_list == NULL) { + /* catch this error by creating a new clist */ + en_att->att_value_list = clist_new(); + if (en_att->att_value_list == NULL) + return MAILIMAP_ERROR_MEMORY; + } + + r = clist_append(en_att->att_value_list, at_value); + if (r < 0) { + return MAILIMAP_ERROR_MEMORY; + } + + return MAILIMAP_NO_ERROR; +} + +struct mailimap_annotatemore_entry_list * +mailimap_annotatemore_entry_list_new(int type, clist * en_att_list, clist * en_list) +{ + struct mailimap_annotatemore_entry_list * entry_list; + + entry_list = malloc(sizeof(* entry_list)); + if (entry_list == NULL) + return NULL; + + entry_list->en_list_type = type; + switch (type) { + case MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_ATT_LIST: + entry_list->en_list_data = en_att_list; + break; + case MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_LIST: + entry_list->en_list_data = en_list; + break; + } + + return entry_list; +} + +void mailimap_annotatemore_entry_list_free(struct + mailimap_annotatemore_entry_list * en_list) +{ + switch(en_list->en_list_type) { + case MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_ATT_LIST: + clist_foreach(en_list->en_list_data, + (clist_func) mailimap_annotatemore_entry_att_free, NULL); + break; + case MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_LIST: + clist_foreach(en_list->en_list_data, + (clist_func) mailimap_annotatemore_entry_free, NULL); + break; + } + clist_free(en_list->en_list_data); + free(en_list); +} + +struct mailimap_annotatemore_annotate_data * +mailimap_annotatemore_annotate_data_new(char * mb, struct + mailimap_annotatemore_entry_list * en_list) +{ + struct mailimap_annotatemore_annotate_data * annotate_data; + + annotate_data = malloc(sizeof(* annotate_data)); + if (annotate_data == NULL) + return NULL; + + annotate_data->mailbox = mb; + annotate_data->entry_list = en_list; + + return annotate_data; +} + +LIBETPAN_EXPORT +void mailimap_annotatemore_annotate_data_free(struct + mailimap_annotatemore_annotate_data * an_data) +{ + mailimap_mailbox_free(an_data->mailbox); + mailimap_annotatemore_entry_list_free(an_data->entry_list); + free(an_data); +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_match_list * +mailimap_annotatemore_entry_match_list_new(clist * en_list) +{ + struct mailimap_annotatemore_entry_match_list * entry_match_list; + + entry_match_list = malloc(sizeof(* entry_match_list)); + if (entry_match_list == NULL) + return NULL; + entry_match_list->entry_match_list = en_list; + + return entry_match_list; +} + +LIBETPAN_EXPORT +void mailimap_annotatemore_entry_match_list_free( + struct mailimap_annotatemore_entry_match_list * en_list) +{ + clist_foreach(en_list->entry_match_list, (clist_func) free, NULL); + clist_free(en_list->entry_match_list); + free(en_list); +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_attrib_match_list * +mailimap_annotatemore_attrib_match_list_new(clist * at_list) +{ + struct mailimap_annotatemore_attrib_match_list * attrib_match_list; + + attrib_match_list = malloc(sizeof(* attrib_match_list)); + if (attrib_match_list == NULL) + return NULL; + attrib_match_list->attrib_match_list = at_list; + + return attrib_match_list; +} + +LIBETPAN_EXPORT +void mailimap_annotatemore_attrib_match_list_free( + struct mailimap_annotatemore_attrib_match_list * at_list) +{ + clist_foreach(at_list->attrib_match_list, (clist_func) free, NULL); + clist_free(at_list->attrib_match_list); + free(at_list); +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_match_list * +mailimap_annotatemore_entry_match_list_new_empty() +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_annotatemore_entry_match_list_new(list); +} + +LIBETPAN_EXPORT +int mailimap_annotatemore_entry_match_list_add( + struct mailimap_annotatemore_entry_match_list * en_list, char * entry) +{ + char * pentry; + int r; + + pentry = strdup(entry); + if (pentry == NULL) + return MAILIMAP_ERROR_MEMORY; + + r = clist_append(en_list->entry_match_list, pentry); + if (r < 0) { + free(pentry); + return MAILIMAP_ERROR_MEMORY; + } + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_attrib_match_list * +mailimap_annotatemore_attrib_match_list_new_empty() +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_annotatemore_attrib_match_list_new(list); +} + +LIBETPAN_EXPORT +int mailimap_annotatemore_attrib_match_list_add( + struct mailimap_annotatemore_attrib_match_list * at_list, char * attrib) +{ + char * pattrib; + int r; + + pattrib = strdup(attrib); + if (pattrib == NULL) + return MAILIMAP_ERROR_MEMORY; + + r = clist_append(at_list->attrib_match_list, pattrib); + if (r < 0) { + free(pattrib); + return MAILIMAP_ERROR_MEMORY; + } + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att_list * +mailimap_annotatemore_entry_att_list_new(clist * en_list) +{ + struct mailimap_annotatemore_entry_att_list * entry_att_list; + + entry_att_list = malloc(sizeof(* entry_att_list)); + if (entry_att_list == NULL) + return NULL; + entry_att_list->entry_att_list = en_list; + + return entry_att_list; +} + +LIBETPAN_EXPORT +void mailimap_annotatemore_entry_att_list_free( + struct mailimap_annotatemore_entry_att_list * en_list) +{ + clist_foreach(en_list->entry_att_list, + (clist_func) mailimap_annotatemore_entry_att_free, NULL); + clist_free(en_list->entry_att_list); + free(en_list); +} + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att_list * +mailimap_annotatemore_entry_att_list_new_empty() +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_annotatemore_entry_att_list_new(list); +} + +LIBETPAN_EXPORT +int mailimap_annotatemore_entry_att_list_add( + struct mailimap_annotatemore_entry_att_list * en_list, + struct mailimap_annotatemore_entry_att * en_att) +{ + int r; + + r = clist_append(en_list->entry_att_list, en_att); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + +void +mailimap_annotatemore_free(struct mailimap_extension_data * ext_data) +{ + if (ext_data == NULL) + return; + + switch (ext_data->ext_type) + { + case MAILIMAP_ANNOTATEMORE_TYPE_ANNOTATE_DATA: + mailimap_annotatemore_annotate_data_free(ext_data->ext_data); + break; + case MAILIMAP_ANNOTATEMORE_TYPE_RESP_TEXT_CODE: + /* nothing malloced for resp_text_code */ + break; + } + + free (ext_data); +} + Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/annotatemore_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,268 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef ANNOTATEMORE_TYPES_H + +#define ANNOTATEMORE_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/libetpan-config.h> +#include <libetpan/mailstream.h> +#include <libetpan/clist.h> + +/* + ANNOTATEMORE grammar + see [draft-daboo-imap-annotatemore-07] for further information + + annotate-data = "ANNOTATION" SP mailbox SP entry-list + ; empty string for mailbox implies + ; server annotation. + + att-value = attrib SP value + + attrib = string + ; dot-separated attribute name + ; MUST NOT contain "*" or "%" + attrib-match = string + ; dot-separated attribute name + ; MAY contain "*" or "%" for use as wildcards + + attribs = attrib-match / "(" attrib-match *(SP attrib-match) ")" + ; attribute specifiers that can include wildcards + + command-auth /= setannotation / getannotation + ; adds to original IMAP command + + entries = entry-match / "(" entry-match *(SP entry-match) ")" + ; entry specifiers that can include wildcards + + entry = string + ; slash-separated path to entry + ; MUST NOT contain "*" or "%" + + entry-att = entry SP "(" att-value *(SP att-value) ")" + + entry-list = entry-att *(SP entry-att) / + "(" entry *(SP entry) ")" + ; entry attribute-value pairs list for + ; GETANNOTATION response, or + ; parenthesised entry list for unsolicited + ; notification of annotation changes + + entry-match = string + ; slash-separated path to entry + ; MAY contain "*" or "%" for use as wildcards + + getannotation = "GETANNOTATION" SP list-mailbox SP entries SP attribs + ; empty string for list-mailbox implies + ; server annotation. + + response-data /= "*" SP annotate-data CRLF + ; adds to original IMAP data responses + + resp-text-code =/ "ANNOTATEMORE" SP "TOOBIG" / + "ANNOTATEMORE" SP "TOOMANY" + ; new response codes for SETANNOTATION failures + + setannotation = "SETANNOTATION" SP list-mailbox SP setentryatt + ; empty string for list-mailbox implies + ; server annotation. + + setentryatt = entry-att / "(" entry-att *(SP entry-att) ")" + + value = nstring +*/ + +/* + only need to recognize types that can be "embedded" into main + IMAPrev1 types. +*/ +enum { + MAILIMAP_ANNOTATEMORE_TYPE_ANNOTATE_DATA, /* child of response-data */ + MAILIMAP_ANNOTATEMORE_TYPE_RESP_TEXT_CODE, /* child of resp-text-code */ +}; + +/* + error codes for annotatemore. +*/ +enum { + MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_UNSPECIFIED, /* unspecified response */ + MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOBIG, /* annotation too big */ + MAILIMAP_ANNOTATEMORE_RESP_TEXT_CODE_TOOMANY, /* too many annotations */ +}; + +void mailimap_annotatemore_attrib_free(char * attrib); + +void mailimap_annotatemore_value_free(char * value); + +void mailimap_annotatemore_entry_free(char * entry); + +struct mailimap_annotatemore_att_value { + char * attrib; + char * value; +}; + +LIBETPAN_EXPORT +struct mailimap_annotatemore_att_value * +mailimap_annotatemore_att_value_new(char * attrib, char * value); + +void mailimap_annotatemore_att_value_free(struct + mailimap_annotatemore_att_value * att_value); + +struct mailimap_annotatemore_entry_att { + char * entry; + clist * att_value_list; + /* list of (struct mailimap_annotatemore_att_value *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att * +mailimap_annotatemore_entry_att_new(char * entry, clist * list); + +LIBETPAN_EXPORT +void mailimap_annotatemore_entry_att_free(struct + mailimap_annotatemore_entry_att * en_att); + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att * +mailimap_annotatemore_entry_att_new_empty(char * entry); + +LIBETPAN_EXPORT +int mailimap_annotatemore_entry_att_add(struct + mailimap_annotatemore_entry_att * en_att, + struct mailimap_annotatemore_att_value * at_value); + +enum { + MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ERROR, /* error condition */ + MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_ATT_LIST, /* entry-att-list */ + MAILIMAP_ANNOTATEMORE_ENTRY_LIST_TYPE_ENTRY_LIST, /* entry-list */ +}; + +struct mailimap_annotatemore_entry_list { + int en_list_type; + clist * en_list_data; + /* either a list of (struct annotatemore_entry_att *) + or a list of (char *) */ +}; + +struct mailimap_annotatemore_entry_list * +mailimap_annotatemore_entry_list_new(int type, clist * en_att_list, clist * en_list); + +void mailimap_annotatemore_entry_list_free(struct + mailimap_annotatemore_entry_list * en_list); + +struct mailimap_annotatemore_annotate_data { + char * mailbox; + struct mailimap_annotatemore_entry_list * entry_list; +}; + +struct mailimap_annotatemore_annotate_data * +mailimap_annotatemore_annotate_data_new(char * mb, struct + mailimap_annotatemore_entry_list * en_list); + +LIBETPAN_EXPORT +void mailimap_annotatemore_annotate_data_free(struct + mailimap_annotatemore_annotate_data * an_data); + +struct mailimap_annotatemore_entry_match_list { + clist * entry_match_list; /* list of (char *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_match_list * +mailimap_annotatemore_entry_match_list_new(clist * en_list); + +LIBETPAN_EXPORT +void mailimap_annotatemore_entry_match_list_free( + struct mailimap_annotatemore_entry_match_list * en_list); + +struct mailimap_annotatemore_attrib_match_list { + clist * attrib_match_list; /* list of (char *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_annotatemore_attrib_match_list * +mailimap_annotatemore_attrib_match_list_new(clist * at_list); + +LIBETPAN_EXPORT +void mailimap_annotatemore_attrib_match_list_free( + struct mailimap_annotatemore_attrib_match_list * at_list); + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_match_list * +mailimap_annotatemore_entry_match_list_new_empty(); + +LIBETPAN_EXPORT +int mailimap_annotatemore_entry_match_list_add( + struct mailimap_annotatemore_entry_match_list * en_list, + char * entry); + +LIBETPAN_EXPORT +struct mailimap_annotatemore_attrib_match_list * +mailimap_annotatemore_attrib_match_list_new_empty(); + +LIBETPAN_EXPORT +int mailimap_annotatemore_attrib_match_list_add( + struct mailimap_annotatemore_attrib_match_list * at_list, + char * attrib); + +struct mailimap_annotatemore_entry_att_list { + clist * entry_att_list; /* list of (mailimap_annotatemore_entry_att *) */ +}; + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att_list * +mailimap_annotatemore_entry_att_list_new(clist * en_list); + +LIBETPAN_EXPORT +void mailimap_annotatemore_entry_att_list_free( + struct mailimap_annotatemore_entry_att_list * en_list); + +LIBETPAN_EXPORT +struct mailimap_annotatemore_entry_att_list * +mailimap_annotatemore_entry_att_list_new_empty(); + +LIBETPAN_EXPORT +int mailimap_annotatemore_entry_att_list_add( + struct mailimap_annotatemore_entry_att_list * en_list, + struct mailimap_annotatemore_entry_att * en_att); + +void +mailimap_annotatemore_free(struct mailimap_extension_data * ext_data); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,2551 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap.c,v 1.37 2006/10/20 00:13:30 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimap.h" +#include "mailimap_parser.h" +#include "mailimap_sender.h" +#include "mailimap_extension.h" +#include "mail.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef USE_SASL +#include <sasl/sasl.h> +#include <sasl/saslutil.h> +#endif + +#include "mailsasl.h" + +#ifdef DEBUG +#include "mailimap_print.h" +#endif + +/* + RFC 2060 : IMAP4rev1 + draft-crispin-imapv-15 + RFC 2222 : Simple Authentication and Security Layer + +2061 IMAP4 Compatibility with IMAP2bis. M. Crispin. December 1996. + (Format: TXT=5867 bytes) (Obsoletes RFC1730) (Status: INFORMATIONAL) + +2062 Internet Message Access Protocol - Obsolete Syntax. M. Crispin. + December 1996. (Format: TXT=14222 bytes) (Status: INFORMATIONAL) + +2086 IMAP4 ACL extension. J. Myers. January 1997. (Format: TXT=13925 + bytes) (Status: PROPOSED STANDARD) + +2087 IMAP4 QUOTA extension. J. Myers. January 1997. (Format: TXT=8542 + bytes) (Status: PROPOSED STANDARD) + +2088 IMAP4 non-synchronizing literals. J. Myers. January 1997. + (Format: TXT=4052 bytes) (Status: PROPOSED STANDARD) + +2177 IMAP4 IDLE command. B. Leiba. June 1997. (Format: TXT=6770 bytes) + (Status: PROPOSED STANDARD) + +2180 IMAP4 Multi-Accessed Mailbox Practice. M. Gahrns. July 1997. + (Format: TXT=24750 bytes) (Status: INFORMATIONAL) + +2192 IMAP URL Scheme. C. Newman. September 1997. (Format: TXT=31426 + bytes) (Status: PROPOSED STANDARD) + +2193 IMAP4 Mailbox Referrals. M. Gahrns. September 1997. (Format: + TXT=16248 bytes) (Status: PROPOSED STANDARD) + +2195 IMAP/POP AUTHorize Extension for Simple Challenge/Response. J. + Klensin, R. Catoe, P. Krumviede. September 1997. (Format: TXT=10468 + bytes) (Obsoletes RFC2095) (Status: PROPOSED STANDARD) + +2221 IMAP4 Login Referrals. M. Gahrns. October 1997. (Format: TXT=9251 + bytes) (Status: PROPOSED STANDARD) + +2342 IMAP4 Namespace. M. Gahrns, C. Newman. May 1998. (Format: + TXT=19489 bytes) (Status: PROPOSED STANDARD) + +2359 IMAP4 UIDPLUS extension. J. Myers. June 1998. (Format: TXT=10862 + bytes) (Status: PROPOSED STANDARD) + +2595 Using TLS with IMAP, POP3 and ACAP. C. Newman. June 1999. + (Format: TXT=32440 bytes) (Status: PROPOSED STANDARD) + +2683 IMAP4 Implementation Recommendations. B. Leiba. September 1999. + (Format: TXT=56300 bytes) (Status: INFORMATIONAL) + +2971 IMAP4 ID extension. T. Showalter. October 2000. (Format: + TXT=14670 bytes) (Status: PROPOSED STANDARD) + +http://www.ietf.org/ids.by.wg/imapext.html +*/ + +static int parse_greeting(mailimap * session, + struct mailimap_greeting ** result); + + +/* struct mailimap_response_info * */ + +static void resp_text_store(mailimap * session, + struct mailimap_resp_text * + resp_text) +{ + struct mailimap_resp_text_code * resp_text_code; + + resp_text_code = resp_text->rsp_code; + + if (resp_text_code != NULL) { + switch (resp_text_code->rc_type) { + case MAILIMAP_RESP_TEXT_CODE_ALERT: + if (session->imap_response_info) + if (session->imap_response_info->rsp_alert != NULL) + free(session->imap_response_info->rsp_alert); + session->imap_response_info->rsp_alert = strdup(resp_text->rsp_text); + break; + + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_badcharset != NULL) { + clist_foreach(resp_text_code->rc_data.rc_badcharset, + (clist_func) mailimap_astring_free, NULL); + clist_free(resp_text_code->rc_data.rc_badcharset); + } + session->imap_response_info->rsp_badcharset = + resp_text_code->rc_data.rc_badcharset; + resp_text_code->rc_data.rc_badcharset = NULL; + } + break; + + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + if (session->imap_connection_info) { + if (session->imap_connection_info->imap_capability != NULL) + mailimap_capability_data_free(session->imap_connection_info->imap_capability); + session->imap_connection_info->imap_capability = + resp_text_code->rc_data.rc_cap_data; + /* detach before free */ + resp_text_code->rc_data.rc_cap_data = NULL; + } + break; + + case MAILIMAP_RESP_TEXT_CODE_PARSE: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_parse != NULL) + free(session->imap_response_info->rsp_parse); + session->imap_response_info->rsp_parse = strdup(resp_text->rsp_text); + } + break; + + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + if (session->imap_selection_info) { + if (session->imap_selection_info->sel_perm_flags != NULL) { + clist_foreach(session->imap_selection_info->sel_perm_flags, + (clist_func) mailimap_flag_perm_free, NULL); + clist_free(session->imap_selection_info->sel_perm_flags); + } + session->imap_selection_info->sel_perm_flags = + resp_text_code->rc_data.rc_perm_flags; + /* detach before free */ + resp_text_code->rc_data.rc_perm_flags = NULL; + } + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_ONLY: + if (session->imap_selection_info) + session->imap_selection_info->sel_perm = MAILIMAP_MAILBOX_READONLY; + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_WRITE: + if (session->imap_selection_info) + session->imap_selection_info->sel_perm = MAILIMAP_MAILBOX_READWRITE; + break; + + case MAILIMAP_RESP_TEXT_CODE_TRY_CREATE: + if (session->imap_response_info) + session->imap_response_info->rsp_trycreate = TRUE; + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: + if (session->imap_selection_info) + session->imap_selection_info->sel_uidnext = + resp_text_code->rc_data.rc_uidnext; + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: + if (session->imap_selection_info) + session->imap_selection_info->sel_uidvalidity = + resp_text_code->rc_data.rc_uidvalidity; + break; + + case MAILIMAP_RESP_TEXT_CODE_UNSEEN: + if (session->imap_selection_info) + session->imap_selection_info->sel_first_unseen = + resp_text_code->rc_data.rc_first_unseen; + break; + + case MAILIMAP_RESP_TEXT_CODE_OTHER: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_atom != NULL) + free(session->imap_response_info->rsp_atom); + if (session->imap_response_info->rsp_value != NULL) + free(session->imap_response_info->rsp_value); + session->imap_response_info->rsp_atom = + resp_text_code->rc_data.rc_atom.atom_name; + resp_text_code->rc_data.rc_atom.atom_name = NULL; + session->imap_response_info->rsp_value = + resp_text_code->rc_data.rc_atom.atom_value; + resp_text_code->rc_data.rc_atom.atom_value = NULL; + } + break; + case MAILIMAP_RESP_TEXT_CODE_EXTENSION: + mailimap_extension_data_store(session, &(resp_text_code->rc_data.rc_ext_data)); + break; + } + } +} + +static void resp_cond_state_store(mailimap * session, + struct mailimap_resp_cond_state * resp_cond_state) +{ + resp_text_store(session, resp_cond_state->rsp_text); +} + +static void mailbox_data_store(mailimap * session, + struct mailimap_mailbox_data * mb_data) +{ + int r; + + switch (mb_data->mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + if (session->imap_selection_info) { + if (session->imap_selection_info->sel_flags != NULL) + mailimap_flag_list_free(session->imap_selection_info->sel_flags); + session->imap_selection_info->sel_flags = mb_data->mbd_data.mbd_flags; + mb_data->mbd_data.mbd_flags = NULL; + } + break; + + case MAILIMAP_MAILBOX_DATA_LIST: + if (session->imap_response_info) { + r = clist_append(session->imap_response_info->rsp_mailbox_list, + mb_data->mbd_data.mbd_list); + if (r == 0) + mb_data->mbd_data.mbd_list = NULL; + else { + /* TODO must handle error case */ + } + } + break; + + case MAILIMAP_MAILBOX_DATA_LSUB: + if (session->imap_response_info) { + r = clist_append(session->imap_response_info->rsp_mailbox_lsub, + mb_data->mbd_data.mbd_lsub); + if (r == 0) + mb_data->mbd_data.mbd_lsub = NULL; + else { + /* TODO must handle error case */ + } + } + break; + + case MAILIMAP_MAILBOX_DATA_SEARCH: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_search_result != NULL) { + if (mb_data->mbd_data.mbd_search != NULL) { + clist_concat(session->imap_response_info->rsp_search_result, + mb_data->mbd_data.mbd_search); + clist_free(mb_data->mbd_data.mbd_search); + mb_data->mbd_data.mbd_search = NULL; + } + } + else { + if (mb_data->mbd_data.mbd_search != NULL) { + session->imap_response_info->rsp_search_result = + mb_data->mbd_data.mbd_search; + mb_data->mbd_data.mbd_search = NULL; + } + } + } + break; + + case MAILIMAP_MAILBOX_DATA_STATUS: + if (session->imap_response_info) { + if (session->imap_response_info->rsp_status != NULL) + mailimap_mailbox_data_status_free(session->imap_response_info->rsp_status); + session->imap_response_info->rsp_status = mb_data->mbd_data.mbd_status; +#if 0 + if (session->imap_selection_info != NULL) { + clistiter * cur; + + for(cur = clist_begin(mb_data->status->status_info_list) + ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_status_info * info; + + info = clist_content(cur); + switch (info->att) { + case MAILIMAP_STATUS_ATT_MESSAGES: + session->imap_selection_info->exists = info->value; + break; + case MAILIMAP_STATUS_ATT_RECENT: + session->imap_selection_info->recent = info->value; + break; + case MAILIMAP_STATUS_ATT_UIDNEXT: + session->imap_selection_info->uidnext = info->value; + break; + case MAILIMAP_STATUS_ATT_UIDVALIDITY: + session->imap_selection_info->uidvalidity = info->value; + break; + case MAILIMAP_STATUS_ATT_UNSEEN: + session->imap_selection_info->unseen = info->value; + break; + } + } + } +#endif +#if 0 + mailimap_mailbox_data_status_free(mb_data->status); +#endif + mb_data->mbd_data.mbd_status = NULL; + } + break; + + case MAILIMAP_MAILBOX_DATA_EXISTS: + if (session->imap_selection_info) + session->imap_selection_info->sel_exists = mb_data->mbd_data.mbd_exists; + break; + + case MAILIMAP_MAILBOX_DATA_RECENT: + if (session->imap_selection_info) + session->imap_selection_info->sel_recent = + mb_data->mbd_data.mbd_recent; + break; + case MAILIMAP_MAILBOX_DATA_EXTENSION_DATA: + if (session->imap_response_info) { + r = clist_append(session->imap_response_info->rsp_extension_list, + mb_data->mbd_data.mbd_extension); + if (r == 0) + mb_data->mbd_data.mbd_extension = NULL; + else { + /* TODO must handle error case */ + } + } + } +} + +static void +message_data_store(mailimap * session, + struct mailimap_message_data * msg_data) +{ + uint32_t * expunged; + int r; + + switch (msg_data->mdt_type) { + case MAILIMAP_MESSAGE_DATA_EXPUNGE: + if (session->imap_response_info) { + expunged = mailimap_number_alloc_new(msg_data->mdt_number); + if (expunged != NULL) { + r = clist_append(session->imap_response_info->rsp_expunged, expunged); + if (r == 0) { + /* do nothing */ + } + else { + /* TODO : must handle error case */ + mailimap_number_alloc_free(expunged); + } + if (session->imap_selection_info != NULL) + session->imap_selection_info->sel_exists --; + } + } + break; + + case MAILIMAP_MESSAGE_DATA_FETCH: + r = clist_append(session->imap_response_info->rsp_fetch_list, + msg_data->mdt_msg_att); + if (r == 0) { + msg_data->mdt_msg_att->att_number = msg_data->mdt_number; + msg_data->mdt_msg_att = NULL; + } + else { + /* TODO : must handle error case */ + } + break; + } +} + +static void +cont_req_or_resp_data_store(mailimap * session, + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data) +{ + if (cont_req_or_resp_data->rsp_type == MAILIMAP_RESP_RESP_DATA) { + struct mailimap_response_data * resp_data; + + resp_data = cont_req_or_resp_data->rsp_data.rsp_resp_data; + + switch (resp_data->rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + resp_cond_state_store(session, resp_data->rsp_data.rsp_cond_state); + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + mailbox_data_store(session, resp_data->rsp_data.rsp_mailbox_data); + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + message_data_store(session, resp_data->rsp_data.rsp_message_data); + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + if (session->imap_connection_info) { + if (session->imap_connection_info->imap_capability != NULL) + mailimap_capability_data_free(session->imap_connection_info->imap_capability); + session->imap_connection_info->imap_capability = resp_data->rsp_data.rsp_capability_data; + resp_data->rsp_data.rsp_capability_data = NULL; + } + break; + case MAILIMAP_RESP_DATA_TYPE_EXTENSION_DATA: + mailimap_extension_data_store(session, &(resp_data->rsp_data.rsp_extension_data)); + break; + } + } +} + +static void response_tagged_store(mailimap * session, + struct mailimap_response_tagged * tagged) +{ + resp_cond_state_store(session, tagged->rsp_cond_state); +} + +static void resp_cond_bye_store(mailimap * session, + struct mailimap_resp_cond_bye * resp_cond_bye) +{ + resp_text_store(session, resp_cond_bye->rsp_text); +} + +static void response_fatal_store(mailimap * session, + struct mailimap_response_fatal * fatal) +{ + resp_cond_bye_store(session, fatal->rsp_bye); +} + +static void response_done_store(mailimap * session, + struct mailimap_response_done * resp_done) +{ + switch(resp_done->rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + response_tagged_store(session, resp_done->rsp_data.rsp_tagged); + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + response_fatal_store(session, resp_done->rsp_data.rsp_fatal); + break; + } +} + +static void +response_store(mailimap * session, + struct mailimap_response * response) +{ + clistiter * cur; + + if (session->imap_response_info) { + mailimap_response_info_free(session->imap_response_info); + session->imap_response_info = NULL; + } + + session->imap_response_info = mailimap_response_info_new(); + if (session->imap_response_info == NULL) { + /* ignored error */ + return; + } + + if (response->rsp_cont_req_or_resp_data_list != NULL) { + for(cur = clist_begin(response->rsp_cont_req_or_resp_data_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data; + + cont_req_or_resp_data = clist_content(cur); + + cont_req_or_resp_data_store(session, cont_req_or_resp_data); + } + } + + response_done_store(session, response->rsp_resp_done); +} + +static void resp_cond_auth_store(mailimap * session, + struct mailimap_resp_cond_auth * cond_auth) +{ + resp_text_store(session, cond_auth->rsp_text); +} + +static void greeting_store(mailimap * session, + struct mailimap_greeting * greeting) +{ + switch (greeting->gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + resp_cond_auth_store(session, greeting->gr_data.gr_auth); + break; + + case MAILIMAP_GREETING_RESP_COND_BYE: + resp_cond_bye_store(session, greeting->gr_data.gr_bye); + break; + } +} + +LIBETPAN_EXPORT +int mailimap_connect(mailimap * session, mailstream * s) +{ + struct mailimap_greeting * greeting; + int r; + int auth_type; + struct mailimap_connection_info * connection_info; + + if (session->imap_state != MAILIMAP_STATE_DISCONNECTED) + return MAILIMAP_ERROR_BAD_STATE; + + session->imap_stream = s; + + if (session->imap_connection_info) + mailimap_connection_info_free(session->imap_connection_info); + connection_info = mailimap_connection_info_new(); + if (connection_info != NULL) + session->imap_connection_info = connection_info; + + if (read_line(session) == NULL) { + return MAILIMAP_ERROR_STREAM; + } + + r = parse_greeting(session, &greeting); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + auth_type = greeting->gr_data.gr_auth->rsp_type; + + mailimap_greeting_free(greeting); + + switch (auth_type) { + case MAILIMAP_RESP_COND_AUTH_PREAUTH: + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_NO_ERROR_AUTHENTICATED; + default: + session->imap_state = MAILIMAP_STATE_NON_AUTHENTICATED; + return MAILIMAP_NO_ERROR_NON_AUTHENTICATED; + } +} + + + + + + + + +/* ********************************************************************** */ + + + +LIBETPAN_EXPORT +int mailimap_append(mailimap * session, const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + const char * literal, size_t literal_size) +{ + struct mailimap_response * response; + int r; + int error_code; + struct mailimap_continue_req * cont_req; + size_t index; + size_t fixed_literal_size; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + fixed_literal_size = mailstream_get_data_crlf_size(literal, literal_size); + + r = mailimap_append_send(session->imap_stream, mailbox, flag_list, date_time, + fixed_literal_size); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + index = 0; + + r = mailimap_continue_req_parse(session->imap_stream, + session->imap_stream_buffer, + &index, &cont_req, + session->imap_progr_rate, session->imap_progr_fun); + if (r == MAILIMAP_NO_ERROR) + mailimap_continue_req_free(cont_req); + + if (r == MAILIMAP_ERROR_PARSE) { + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + mailimap_response_free(response); + + return MAILIMAP_ERROR_APPEND; + } + + r = mailimap_literal_data_send(session->imap_stream, literal, literal_size, + session->imap_progr_rate, session->imap_progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_APPEND; + } +} + +LIBETPAN_EXPORT +int mailimap_noop(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_noop_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_NOOP; + } +} + +LIBETPAN_EXPORT +int mailimap_logout(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + int res; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + r = mailimap_logout_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + if (mailstream_flush(session->imap_stream) == -1) { + res = MAILIMAP_ERROR_STREAM; + goto close; + } + + if (read_line(session) == NULL) { + res = MAILIMAP_ERROR_STREAM; + goto close; + } + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto close; + } + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + if (session->imap_connection_info) { + mailimap_connection_info_free(session->imap_connection_info); + session->imap_connection_info = NULL; + } + res = MAILIMAP_NO_ERROR; + goto close; + + default: + res = MAILIMAP_ERROR_LOGOUT; + goto close; + } + + close: + mailstream_close(session->imap_stream); + session->imap_stream = NULL; + session->imap_state = MAILIMAP_STATE_DISCONNECTED; + return res; +} + +/* send the results back to the caller */ +/* duplicate the result */ + +static struct mailimap_capability * +mailimap_capability_dup(struct mailimap_capability * orig_cap) +{ + struct mailimap_capability * cap; + char * auth_type; + char * name; + + name = NULL; + auth_type = NULL; + switch (orig_cap->cap_type) { + case MAILIMAP_CAPABILITY_NAME: + name = strdup(orig_cap->cap_data.cap_name); + if (name == NULL) + goto err; + break; + case MAILIMAP_CAPABILITY_AUTH_TYPE: + auth_type = strdup(orig_cap->cap_data.cap_auth_type); + if (auth_type == NULL) + goto err; + break; + } + + cap = mailimap_capability_new(orig_cap->cap_type, auth_type, name); + if (cap == NULL) + goto free; + + return cap; + + free: + if (name != NULL) + free(name); + if (auth_type != NULL) + free(auth_type); + err: + return NULL; +} + +static struct mailimap_capability_data * +mailimap_capability_data_dup(struct mailimap_capability_data * orig_cap_data) +{ + struct mailimap_capability_data * cap_data; + struct mailimap_capability * cap_dup; + clist * list; + clistiter * cur; + int r; + + list = clist_new(); + if (list == NULL) + goto err; + + for(cur = clist_begin(orig_cap_data->cap_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_capability * cap; + + cap = clist_content(cur); + + cap_dup = mailimap_capability_dup(cap); + if (cap_dup == NULL) + goto list; + + r = clist_append(list, cap_dup); + if (r < 0) { + mailimap_capability_free(cap_dup); + goto list; + } + } + + cap_data = mailimap_capability_data_new(list); + if (cap_data == NULL) + goto list; + + return cap_data; + +list: + clist_foreach(list, (clist_func) mailimap_capability_free, NULL); + clist_free(list); +err: + return NULL; +} + +LIBETPAN_EXPORT +int mailimap_capability(mailimap * session, + struct mailimap_capability_data ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + struct mailimap_capability_data * cap_data; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_capability_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + cap_data = + mailimap_capability_data_dup(session->imap_connection_info->imap_capability); + if (cap_data == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = cap_data; + + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CAPABILITY; + } +} + +LIBETPAN_EXPORT +int mailimap_check(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_check_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CHECK; + } +} + +LIBETPAN_EXPORT +int mailimap_close(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_close_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + /* leave selected state */ + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = NULL; + + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CLOSE; + } +} + +LIBETPAN_EXPORT +int mailimap_expunge(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_expunge_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXPUNGE; + } +} + +LIBETPAN_EXPORT +int mailimap_copy(mailimap * session, struct mailimap_set * set, + const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_copy_send(session->imap_stream, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_COPY; + } +} + +LIBETPAN_EXPORT +int mailimap_uid_copy(mailimap * session, struct mailimap_set * set, + const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_copy_send(session->imap_stream, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_COPY; + } +} + +LIBETPAN_EXPORT +int mailimap_create(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_create_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_CREATE; + } +} + + +LIBETPAN_EXPORT +int mailimap_delete(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_delete_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_DELETE; + } +} + +LIBETPAN_EXPORT +int mailimap_examine(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_examine_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + if (session->imap_selection_info != NULL) + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = mailimap_selection_info_new(); + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_SELECTED; + return MAILIMAP_NO_ERROR; + + default: + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = NULL; + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_ERROR_EXAMINE; + } +} + +LIBETPAN_EXPORT +int +mailimap_fetch(mailimap * session, struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fetch_send(session->imap_stream, set, fetch_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_fetch_list; + session->imap_response_info->rsp_fetch_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_FETCH; + } +} + +LIBETPAN_EXPORT +void mailimap_fetch_list_free(clist * fetch_list) +{ + clist_foreach(fetch_list, (clist_func) mailimap_msg_att_free, NULL); + clist_free(fetch_list); +} + +LIBETPAN_EXPORT +int +mailimap_uid_fetch(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_fetch_send(session->imap_stream, set, fetch_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_fetch_list; + session->imap_response_info->rsp_fetch_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_FETCH; + } +} + +LIBETPAN_EXPORT +int mailimap_list(mailimap * session, const char * mb, + const char * list_mb, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_send(session->imap_stream, mb, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_mailbox_list; + session->imap_response_info->rsp_mailbox_list = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_LIST; + } +} + +LIBETPAN_EXPORT +int mailimap_login(mailimap * session, + const char * userid, const char * password) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_NON_AUTHENTICATED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_login_send(session->imap_stream, userid, password); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_LOGIN; + } +} + +#ifdef USE_SASL +static int sasl_getsimple(void * context, int id, + const char ** result, unsigned * len) +{ + mailimap * session; + + session = context; + + switch (id) { + case SASL_CB_USER: + if (result != NULL) + * result = session->imap_sasl.sasl_login; + if (len != NULL) + * len = strlen(session->imap_sasl.sasl_login); + return SASL_OK; + + case SASL_CB_AUTHNAME: + if (result != NULL) + * result = session->imap_sasl.sasl_auth_name; + if (len != NULL) + * len = strlen(session->imap_sasl.sasl_auth_name); + return SASL_OK; + } + + return SASL_FAIL; +} + +static int sasl_getsecret(sasl_conn_t * conn, void * context, int id, + sasl_secret_t ** psecret) +{ + mailimap * session; + + session = context; + + switch (id) { + case SASL_CB_PASS: + if (psecret != NULL) + * psecret = session->imap_sasl.sasl_secret; + return SASL_OK; + } + + return SASL_FAIL; +} + +static int sasl_getrealm(void * context, int id, + const char ** availrealms, + const char ** result) +{ + mailimap * session; + + session = context; + + switch (id) { + case SASL_CB_GETREALM: + if (result != NULL) + * result = session->imap_sasl.sasl_realm; + return SASL_OK; + } + + return SASL_FAIL; +} +#endif + +LIBETPAN_EXPORT +int mailimap_authenticate(mailimap * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ +#ifdef USE_SASL + struct mailimap_response * response; + int r; + int error_code; + size_t index; + struct mailimap_cont_req_or_resp_data * cont_or_resp_data; + sasl_callback_t sasl_callback[5]; + const char * sasl_out; + unsigned sasl_out_len; + const char * mechusing; + sasl_secret_t * secret; + int res; + size_t len; + + if (session->imap_state != MAILIMAP_STATE_NON_AUTHENTICATED) { + res = MAILIMAP_ERROR_BAD_STATE; + goto err; + } + + sasl_callback[0].id = SASL_CB_GETREALM; + sasl_callback[0].proc = sasl_getrealm; + sasl_callback[0].context = session; + sasl_callback[1].id = SASL_CB_USER; + sasl_callback[1].proc = sasl_getsimple; + sasl_callback[1].context = session; + sasl_callback[2].id = SASL_CB_AUTHNAME; + sasl_callback[2].proc = sasl_getsimple; + sasl_callback[2].context = session; + sasl_callback[3].id = SASL_CB_PASS; + sasl_callback[3].proc = sasl_getsecret; + sasl_callback[3].context = session; + sasl_callback[4].id = SASL_CB_LIST_END; + sasl_callback[4].proc = NULL; + sasl_callback[4].context = NULL; + + len = strlen(password); + secret = malloc(sizeof(* secret) + len); + if (secret == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + secret->len = len; + memcpy(secret->data, password, len + 1); + + session->imap_sasl.sasl_server_fqdn = server_fqdn; + session->imap_sasl.sasl_login = login; + session->imap_sasl.sasl_auth_name = auth_name; + session->imap_sasl.sasl_password = password; + session->imap_sasl.sasl_realm = realm; + session->imap_sasl.sasl_secret = secret; + + /* init SASL */ + if (session->imap_sasl.sasl_conn != NULL) { + sasl_dispose((sasl_conn_t **) &session->imap_sasl.sasl_conn); + session->imap_sasl.sasl_conn = NULL; + } + else { + mailsasl_ref(); + } + + r = sasl_client_new("imap", server_fqdn, + local_ip_port, remote_ip_port, sasl_callback, 0, + (sasl_conn_t **) &session->imap_sasl.sasl_conn); + if (r != SASL_OK) { + res = MAILIMAP_ERROR_LOGIN; + goto free_secret; + } + + r = sasl_client_start(session->imap_sasl.sasl_conn, + auth_type, NULL, &sasl_out, &sasl_out_len, &mechusing); + if ((r != SASL_CONTINUE) && (r != SASL_OK)) { + res = MAILIMAP_ERROR_LOGIN; + goto free_sasl_conn; + } + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_sasl_conn; + } + + r = mailimap_authenticate_send(session->imap_stream, auth_type); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_sasl_conn; + } + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_sasl_conn; + } + + if (mailstream_flush(session->imap_stream) == -1) { + res = MAILIMAP_ERROR_STREAM; + goto free_sasl_conn; + } + + while (1) { + struct mailimap_continue_req * cont_req; + char * response; + int got_response; + char * encoded; + unsigned int encoded_len; + unsigned int max_encoded; + + if (read_line(session) == NULL) { + res = MAILIMAP_ERROR_STREAM; + goto free_sasl_conn; + } + + index = 0; + + r = mailimap_continue_req_parse(session->imap_stream, + session->imap_stream_buffer, + &index, &cont_req, + session->imap_progr_rate, session->imap_progr_fun); + if (r != MAILIMAP_NO_ERROR) + break; + + got_response = 1; + if (cont_req->cr_type == MAILIMAP_CONTINUE_REQ_BASE64) { + response = cont_req->cr_data.cr_base64; + if (* response == '\0') + got_response = 0; + } + else { + response = ""; + got_response = 0; + } + + if (got_response) { + size_t response_len; + char * decoded; + unsigned int decoded_len; + unsigned int max_decoded; + + response_len = strlen(response); + max_decoded = response_len * 3 / 4; + decoded = malloc(max_decoded + 1); + if (decoded == NULL) { + mailimap_continue_req_free(cont_req); + res = MAILIMAP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_decode64(response, response_len, + decoded, max_decoded + 1, &decoded_len); + + mailimap_continue_req_free(cont_req); + + if (r != SASL_OK) { + free(decoded); + res = MAILIMAP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_client_step(session->imap_sasl.sasl_conn, + decoded, decoded_len, NULL, &sasl_out, &sasl_out_len); + + free(decoded); + + if ((r != SASL_CONTINUE) && (r != SASL_OK)) { + res = MAILIMAP_ERROR_LOGIN; + goto free_sasl_conn; + } + } + else { + mailimap_continue_req_free(cont_req); + } + + max_encoded = ((sasl_out_len + 2) / 3) * 4; + encoded = malloc(max_encoded + 1); + if (encoded == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_encode64(sasl_out, sasl_out_len, + encoded, max_encoded + 1, &encoded_len); + if (r != SASL_OK) { + free(encoded); + res = MAILIMAP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = mailimap_token_send(session->imap_stream, encoded); + + free(encoded); + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_sasl_conn; + } + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_sasl_conn; + } + + if (mailstream_flush(session->imap_stream) == -1) { + res = MAILIMAP_ERROR_STREAM; + goto free_sasl_conn; + } + } + + free(session->imap_sasl.sasl_secret); + session->imap_sasl.sasl_secret = NULL; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_sasl_conn; + } + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + res = MAILIMAP_NO_ERROR; + goto free_sasl_conn; + + default: + res = MAILIMAP_ERROR_LOGIN; + goto free_sasl_conn; + } + + free_sasl_conn: + sasl_dispose((sasl_conn_t **) &session->imap_sasl.sasl_conn); + session->imap_sasl.sasl_conn = NULL; + mailsasl_unref(); + free_secret: + free(session->imap_sasl.sasl_secret); + session->imap_sasl.sasl_secret = NULL; + err: + return res; +#else + return MAILIMAP_ERROR_LOGIN; +#endif +} + + +LIBETPAN_EXPORT +int mailimap_lsub(mailimap * session, const char * mb, + const char * list_mb, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_lsub_send(session->imap_stream, mb, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_mailbox_lsub; + session->imap_response_info->rsp_mailbox_lsub = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_LSUB; + } +} + +LIBETPAN_EXPORT +void mailimap_list_result_free(clist * list) +{ + clist_foreach(list, (clist_func) mailimap_mailbox_list_free, NULL); + clist_free(list); +} + +LIBETPAN_EXPORT +int mailimap_rename(mailimap * session, + const char * mb, const char * new_name) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_rename_send(session->imap_stream, mb, new_name); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (!mailimap_crlf_send(session->imap_stream)) + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_RENAME; + } +} + +LIBETPAN_EXPORT +int +mailimap_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_search_send(session->imap_stream, charset, key); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_search_result; + session->imap_response_info->rsp_search_result = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_SEARCH; + } +} + +LIBETPAN_EXPORT +int +mailimap_uid_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_search_send(session->imap_stream, charset, key); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_search_result; + session->imap_response_info->rsp_search_result = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_SEARCH; + } +} + +LIBETPAN_EXPORT +void mailimap_search_result_free(clist * search_result) +{ + clist_foreach(search_result, (clist_func) free, NULL); + clist_free(search_result); +} + +LIBETPAN_EXPORT +int +mailimap_select(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_select_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + if (session->imap_selection_info != NULL) + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = mailimap_selection_info_new(); + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + session->imap_state = MAILIMAP_STATE_SELECTED; + return MAILIMAP_NO_ERROR; + + default: + mailimap_selection_info_free(session->imap_selection_info); + session->imap_selection_info = NULL; + session->imap_state = MAILIMAP_STATE_AUTHENTICATED; + return MAILIMAP_ERROR_SELECT; + } +} + +LIBETPAN_EXPORT +int +mailimap_status(mailimap * session, const char * mb, + struct mailimap_status_att_list * status_att_list, + struct mailimap_mailbox_data_status ** result) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_status_send(session->imap_stream, mb, status_att_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = session->imap_response_info->rsp_status; + session->imap_response_info->rsp_status = NULL; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_STATUS; + } +} + + +LIBETPAN_EXPORT +int +mailimap_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_store_send(session->imap_stream, set, store_att_flags); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_STORE; + } +} + +LIBETPAN_EXPORT +int +mailimap_uid_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_store_send(session->imap_stream, set, store_att_flags); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UID_STORE; + } +} + +LIBETPAN_EXPORT +int mailimap_subscribe(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_subscribe_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_SUBSCRIBE; + } +} + +LIBETPAN_EXPORT +int mailimap_unsubscribe(mailimap * session, const char * mb) +{ + struct mailimap_response * response; + int r; + int error_code; + + if ((session->imap_state != MAILIMAP_STATE_AUTHENTICATED) && + (session->imap_state != MAILIMAP_STATE_SELECTED)) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_unsubscribe_send(session->imap_stream, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_UNSUBSCRIBE; + } +} + + +LIBETPAN_EXPORT +int mailimap_starttls(mailimap * session) +{ + struct mailimap_response * response; + int r; + int error_code; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_starttls_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_STARTTLS; + } +} + + + +char * read_line(mailimap * session) +{ + return mailstream_read_line(session->imap_stream, session->imap_stream_buffer); +} + +int send_current_tag(mailimap * session) +{ + char tag_str[15]; + int r; + + session->imap_tag ++; + snprintf(tag_str, 15, "%i", session->imap_tag); + + r = mailimap_tag_send(session->imap_stream, tag_str); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int parse_response(mailimap * session, + struct mailimap_response ** result) +{ + size_t index; + struct mailimap_response * response; + char tag_str[15]; + int r; + + index = 0; + + session->imap_response = NULL; + + r = mailimap_response_parse(session->imap_stream, + session->imap_stream_buffer, + &index, &response, + session->imap_progr_rate, session->imap_progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + +#if 0 + mailimap_response_print(response); +#endif + + response_store(session, response); + + if (response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_text->rsp_text != NULL) { + if (mmap_string_assign(session->imap_response_buffer, + response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_text->rsp_text) + == NULL) + return MAILIMAP_ERROR_MEMORY; + } + + session->imap_response = session->imap_response_buffer->str; + + if (response->rsp_resp_done->rsp_type == MAILIMAP_RESP_DONE_TYPE_FATAL) + return MAILIMAP_ERROR_FATAL; + + snprintf(tag_str, 15, "%i", session->imap_tag); + if (strcmp(response->rsp_resp_done->rsp_data.rsp_tagged->rsp_tag, tag_str) != 0) + return MAILIMAP_ERROR_PROTOCOL; + + if (response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type == + MAILIMAP_RESP_COND_STATE_BAD) + return MAILIMAP_ERROR_PROTOCOL; + + * result = response; + + return MAILIMAP_NO_ERROR; +} + + +static int parse_greeting(mailimap * session, + struct mailimap_greeting ** result) +{ + size_t index; + struct mailimap_greeting * greeting; + int r; + + index = 0; + + session->imap_response = NULL; + + r = mailimap_greeting_parse(session->imap_stream, + session->imap_stream_buffer, + &index, &greeting, session->imap_progr_rate, + session->imap_progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + +#if 0 + mailimap_greeting_print(greeting); +#endif + + greeting_store(session, greeting); + + if (greeting->gr_type == MAILIMAP_GREETING_RESP_COND_BYE) { + if (mmap_string_assign(session->imap_response_buffer, + greeting->gr_data.gr_bye->rsp_text->rsp_text) == NULL) + return MAILIMAP_ERROR_MEMORY; + + session->imap_response = session->imap_response_buffer->str; + + return MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION; + } + + if (mmap_string_assign(session->imap_response_buffer, + greeting->gr_data.gr_auth->rsp_text->rsp_text) == NULL) + return MAILIMAP_ERROR_MEMORY; + + session->imap_response = session->imap_response_buffer->str; + + * result = greeting; + + return MAILIMAP_NO_ERROR; +} + + +LIBETPAN_EXPORT +mailimap * mailimap_new(size_t imap_progr_rate, + progress_function * imap_progr_fun) +{ + mailimap * f; + + f = malloc(sizeof(* f)); + if (f == NULL) + goto err; + + f->imap_response = NULL; + + f->imap_stream = NULL; + + f->imap_progr_rate = imap_progr_rate; + f->imap_progr_fun = imap_progr_fun; + + f->imap_stream_buffer = mmap_string_new(""); + if (f->imap_stream_buffer == NULL) + goto free_f; + + f->imap_response_buffer = mmap_string_new(""); + if (f->imap_response_buffer == NULL) + goto free_stream_buffer; + + f->imap_state = MAILIMAP_STATE_DISCONNECTED; + f->imap_tag = 0; + + f->imap_selection_info = NULL; + f->imap_response_info = NULL; + f->imap_connection_info = NULL; + +#ifdef USE_SASL + f->imap_sasl.sasl_conn = NULL; +#endif + + return f; + + free_stream_buffer: + mmap_string_free(f->imap_stream_buffer); + free_f: + free(f); + err: + return NULL; +} + +LIBETPAN_EXPORT +void mailimap_free(mailimap * session) +{ +#ifdef USE_SASL + if (session->imap_sasl.sasl_conn != NULL) { + sasl_dispose((sasl_conn_t **) &session->imap_sasl.sasl_conn); + mailsasl_unref(); + } +#endif + + if (session->imap_stream) + mailimap_logout(session); + + mmap_string_free(session->imap_response_buffer); + mmap_string_free(session->imap_stream_buffer); + + if (session->imap_response_info) + mailimap_response_info_free(session->imap_response_info); + if (session->imap_selection_info) + mailimap_selection_info_free(session->imap_selection_info); + if (session->imap_connection_info) + mailimap_connection_info_free(session->imap_connection_info); + + free(session); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,658 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap.h,v 1.18 2006/10/20 00:13:30 hoa Exp $ + */ + +#ifndef MAILIMAP_H + +#define MAILIMAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailimap_types.h> +#include <libetpan/mailimap_types_helper.h> +#include <libetpan/mailimap_helper.h> + +#include <libetpan/mailimap_socket.h> +#include <libetpan/mailimap_ssl.h> + +#include <libetpan/acl.h> +#include <libetpan/annotatemore.h> +#include <libetpan/uidplus.h> + +/* + mailimap_connect() + + This function will connect the IMAP session with the given stream. + + @param session the IMAP session + @param s stream to use + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + + note that on success, MAILIMAP_NO_ERROR_AUTHENTICATED or + MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned + + MAILIMAP_NO_ERROR_NON_AUTHENTICATED is returned when you need to + use mailimap_login() to authenticate, else + MAILIMAP_NO_ERROR_AUTHENTICATED is returned. +*/ + +LIBETPAN_EXPORT +int mailimap_connect(mailimap * session, mailstream * s); + +/* + mailimap_append() + + This function will append a given message to the given mailbox + by sending an APPEND command. + + @param session the IMAP session + @param mailbox name of the mailbox + @param flag_list flags of the message + @param date_time timestamp of the message + @param literal content of the message + @param literal_size size of the message + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_append(mailimap * session, const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + const char * literal, size_t literal_size); + +/* + mailimap_noop() + + This function will poll for an event on the server by + sending a NOOP command to the IMAP server + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR_XXX codes +*/ + +LIBETPAN_EXPORT +int mailimap_noop(mailimap * session); + +/* + mailimap_logout() + + This function will logout from an IMAP server by sending + a LOGOUT command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_logout(mailimap * session); + +/* + mailimap_capability() + + This function will query an IMAP server for his capabilities + by sending a CAPABILITY command. + + @param session IMAP session + @param result The result of this command is a list of + capabilities and it is stored into (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_capability(mailimap * session, + struct mailimap_capability_data ** result); + +/* + mailimap_check() + + This function will request for a checkpoint of the mailbox by + sending a CHECK command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_check(mailimap * session); + +/* + mailimap_close() + + This function will close the selected mailbox by sending + a CLOSE command. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_close(mailimap * session); + +/* + mailimap_expunge() + + This function will permanently remove from the selected mailbox + message that have the \Deleted flag set. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_expunge(mailimap * session); + +/* + mailimap_copy() + + This function will copy the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message numbers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_copy(mailimap * session, struct mailimap_set * set, + const char * mb); + +/* + mailimap_uid_copy() + + This function will copy the given messages from the selected mailbox + to the given mailbox. + + @param session IMAP session + @param set This is a set of message unique identifiers. + @param mb This is the destination mailbox. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes + */ + +LIBETPAN_EXPORT +int mailimap_uid_copy(mailimap * session, + struct mailimap_set * set, const char * mb); + +/* + mailimap_create() + + This function will create a mailbox. + + @param session IMAP session + @param mb This is the name of the mailbox to create. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_create(mailimap * session, const char * mb); + +/* + mailimap_delete() + + This function will delete a mailox. + + @param session IMAP session + @param mb This is the name of the mailbox to delete. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_delete(mailimap * session, const char * mb); + +/* + mailimap_examine() + + This function will select the mailbox for read-only operations. + + @param session IMAP session + @param mb This is the name of the mailbox to select. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_examine(mailimap * session, const char * mb); + +/* + mailimap_fetch() + + This function will retrieve data associated with the given message + numbers. + + @param session IMAP session + @param set set of message numbers + @param fetch_type type of information to be retrieved + @param result The result of this command is a clist + and it is stored into (* result). Each element of the clist is a + (struct mailimap_msg_att *). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_fetch(mailimap * session, struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result); + +/* + mailimap_fetch() + + This function will retrieve data associated with the given message + numbers. + + @param session IMAP session + @param set set of message unique identifiers + @param fetch_type type of information to be retrieved + @param result The result of this command is a clist + and it is stored into (* result). Each element of the clist is a + (struct mailimap_msg_att *). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_uid_fetch(mailimap * session, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type, clist ** result); + +/* + mailimap_fetch_list_free() + + This function will free the result of a fetch command. + + @param fetch_list This is the clist containing + (struct mailimap_msg_att *) elements to free. +*/ + +LIBETPAN_EXPORT +void mailimap_fetch_list_free(clist * fetch_list); + +/* + mailimap_list() + + This function will return the list of the mailbox + available on the server. + + @param session IMAP session + @param mb This is the reference name that informs + of the level of hierarchy + @param list_mb mailbox name with possible wildcard + @param result This will store a clist of (struct mailimap_mailbox_list *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_list(mailimap * session, const char * mb, + const char * list_mb, clist ** result); + +/* + mailimap_login() + + This function will authenticate the client. + + @param session IMAP session + @param userid login of the user + @param password password of the user + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_login(mailimap * session, + const char * userid, const char * password); + +/* + mailimap_authenticate() + + This function will authenticate the client. + TODO : documentation +*/ + +LIBETPAN_EXPORT +int mailimap_authenticate(mailimap * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + + +/* + mailimap_lsub() + + This function will return the list of the mailbox + that the client has subscribed to. + + @param session IMAP session + @param mb This is the reference name that informs + of the level of hierarchy + @param list_mb mailbox name with possible wildcard + @param result This will store a list of (struct mailimap_mailbox_list *) + in (* result) + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_lsub(mailimap * session, const char * mb, + const char * list_mb, clist ** result); + +/* + mailimap_list_result_free() + + This function will free the clist of (struct mailimap_mailbox_list *) + + @param list This is the clist to free. +*/ + +LIBETPAN_EXPORT +void mailimap_list_result_free(clist * list); + +/* + mailimap_rename() + + This function will change the name of a mailbox. + + @param session IMAP session + @param mb current name + @param new_name new name + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_rename(mailimap * session, + const char * mb, const char * new_name); + +/* + mailimap_search() + + All mails that match the given criteria will be returned + their numbers in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_uid_search() + + + All mails that match the given criteria will be returned + their unique identifiers in the result list. + + @param session IMAP session + @param charset This indicates the charset of the strings that appears + in the searching criteria + @param key This is the searching criteria + @param result The result is a clist of (uint32_t *) and will be + stored in (* result). + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_uid_search(mailimap * session, const char * charset, + struct mailimap_search_key * key, clist ** result); + +/* + mailimap_search_result_free() + + This function will free the result of the a search. + + @param search_result This is a clist of (uint32_t *) returned + by mailimap_uid_search() or mailimap_search() +*/ + +LIBETPAN_EXPORT +void mailimap_search_result_free(clist * search_result); + +/* + mailimap_select() + + This function will select a given mailbox so that messages in the + mailbox can be accessed. + + @param session IMAP session + @param mb This is the name of the mailbox to select. + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_select(mailimap * session, const char * mb); + +/* + mailimap_status() + + This function will return informations about a given mailbox. + + @param session IMAP session + @param mb This is the name of the mailbox + @param status_att_list This is the list of mailbox information to return + @param result List of returned values + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_status(mailimap * session, const char * mb, + struct mailimap_status_att_list * status_att_list, + struct mailimap_mailbox_data_status ** result); + +/* + mailimap_uid_store() + + This function will alter the data associated with some messages + (flags of the messages). + + @param session IMAP session + @param set This is a list of message numbers. + @param store_att_flags This is the data to associate with the + given messages + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +/* + mailimap_uid_store() + + This function will alter the data associated with some messages + (flags of the messages). + + @param session IMAP session + @param set This is a list of message unique identifiers. + @param store_att_flags This is the data to associate with the + given messages + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int +mailimap_uid_store(mailimap * session, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +/* + mailimap_subscribe() + + This function adds the specified mailbox name to the + server's set of "active" or "subscribed" mailboxes. + + @param session IMAP session + @param mb This is the name of the mailbox + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_subscribe(mailimap * session, const char * mb); + +/* + mailimap_unsubscribe() + + This function removes the specified mailbox name to the + server's set of "active" or "subscribed" mailboxes. + + @param session IMAP session + @param mb This is the name of the mailbox + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR codes +*/ + +LIBETPAN_EXPORT +int mailimap_unsubscribe(mailimap * session, const char * mb); + +/* + mailimap_starttls() + + This function starts change the mode of the connection to + switch to SSL connection. + + @param session IMAP session + + @return the return code is one of MAILIMAP_ERROR_XXX or + MAILIMAP_NO_ERROR_XXX codes + */ + +LIBETPAN_EXPORT +int mailimap_starttls(mailimap * session); + +/* + mailimap_new() + + This function returns a new IMAP session. + + @param progr_rate When downloading messages, a function will be called + each time the amount of bytes downloaded reaches a multiple of this + value, this can be 0. + @param progr_fun This is the function to call to notify the progress, + this can be NULL. + + @return an IMAP session is returned. + */ + +LIBETPAN_EXPORT +mailimap * mailimap_new(size_t imap_progr_rate, + progress_function * imap_progr_fun); + +/* + mailimap_free() + + This function will free the data structures associated with + the IMAP session. + + @param session IMAP session + */ + +LIBETPAN_EXPORT +void mailimap_free(mailimap * session); + +int send_current_tag(mailimap * session); + +char * read_line(mailimap * session); + +int parse_response(mailimap * session, + struct mailimap_response ** result); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_extension.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_extension.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,191 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimap_extension.h" + +#include <stdlib.h> +#include <stdio.h> + +#include "clist.h" +#include "annotatemore.h" +#include "acl.h" +#include "uidplus.h" + +/* + the list of registered extensions (struct mailimap_extension_api *) + + the list of extension is kept as a simple clist. +*/ + +static clist * mailimap_extension_list = NULL; + +static struct mailimap_extension_api * internal_extension_list[] = { + &mailimap_extension_annotatemore, + &mailimap_extension_acl, + &mailimap_extension_uidplus, +}; + +LIBETPAN_EXPORT +int +mailimap_extension_register(struct mailimap_extension_api * extension) +{ + if (mailimap_extension_list == NULL) { + mailimap_extension_list = clist_new(); + if (mailimap_extension_list == NULL) + return MAILIMAP_ERROR_MEMORY; + } + + return clist_append(mailimap_extension_list, extension); +} + +LIBETPAN_EXPORT +void +mailimap_extension_unregister_all(void) +{ + clist_free(mailimap_extension_list); + mailimap_extension_list = NULL; +} + +LIBETPAN_EXPORT +int +mailimap_extension_data_parse(int calling_parser, + mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clistiter * cur; + int r; + unsigned int i; + + for(i = 0 ; i < sizeof(internal_extension_list) / sizeof(* internal_extension_list) ; i ++) { + struct mailimap_extension_api * ext; + + ext = internal_extension_list[i]; + r = ext->ext_parser(calling_parser, fd, buffer, index, result, + progr_rate, progr_fun); + if (r != MAILIMAP_ERROR_PARSE) + return r; + } + + if (mailimap_extension_list == NULL) + return MAILIMAP_ERROR_PARSE; + + for (cur = clist_begin(mailimap_extension_list); + cur != NULL; cur = clist_next(cur)) { + struct mailimap_extension_api * ext; + + ext = clist_content(cur); + r = ext->ext_parser(calling_parser, fd, buffer, index, result, + progr_rate, progr_fun); + if (r != MAILIMAP_ERROR_PARSE) + return r; + } + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +struct mailimap_extension_data * +mailimap_extension_data_new(struct mailimap_extension_api * extension, + int type, void * data) +{ + struct mailimap_extension_data * ext_data; + + ext_data = malloc(sizeof(* ext_data)); + if (ext_data == NULL) + return NULL; + + ext_data->ext_extension = extension; + ext_data->ext_type = type; + ext_data->ext_data = data; + + return ext_data; +} + +LIBETPAN_EXPORT +void +mailimap_extension_data_free(struct + mailimap_extension_data * data) +{ + if (data == NULL) + return; + + if (data->ext_extension != NULL) + data->ext_extension->ext_free(data); + else + free(data); +} + +void mailimap_extension_data_store(mailimap * session, + struct mailimap_extension_data ** ext_data) +{ + int r; + + if (session->imap_response_info) { + r = clist_append(session->imap_response_info->rsp_extension_list, + * ext_data); + if (r == 0) + * ext_data = NULL; + else { + /* TODO must handle error case */ + } + } +} + +LIBETPAN_EXPORT +int mailimap_has_extension(mailimap * session, char * extension_name) +{ + if (session->imap_connection_info != NULL) { + if (session->imap_connection_info->imap_capability != NULL) { + clist * list; + clistiter * cur; + + list = session->imap_connection_info->imap_capability->cap_list; + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_capability * cap; + + cap = clist_content(cur); + if (cap->cap_type != MAILIMAP_CAPABILITY_NAME) + continue; + + if (strcasecmp(cap->cap_data.cap_name, extension_name) == 0) + return 1; + } + } + } + + return 0; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_extension.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_extension.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,108 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef MAILIMAP_EXTENSION_H + +#define MAILIMAP_EXTENSION_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailimap_types.h> +#include <libetpan/mailimap_extension_types.h> + +/* + you add a (static) mailimap_extension_api to the list of extensions + by calling register. making the list of + extensions contain all extensions statically may prove detrimental + to speed if you have many extensions and don't need any of them. + as unregistering single extensions does not really make any sense, + it's not provided - just an unregister_all which is primarily used + to free the clist on exit. +*/ + +LIBETPAN_EXPORT +int +mailimap_extension_register(struct mailimap_extension_api * extension); + +LIBETPAN_EXPORT +void +mailimap_extension_unregister_all(void); + +/* + this is called as the main parser wrapper for all extensions. + it gos through the list of registered extensions and calls + all of the extensions' parsers looking for one that doesn't + return MAILIMAP_ERROR_PARSE. +*/ +LIBETPAN_EXPORT +int +mailimap_extension_data_parse(int calling_parser, + mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +LIBETPAN_EXPORT +struct mailimap_extension_data * +mailimap_extension_data_new(struct mailimap_extension_api * extension, + int type, void * data); + +/* + wrapper for the extensions' free. calls the correct extension's free + based on data->extension. +*/ +LIBETPAN_EXPORT +void +mailimap_extension_data_free(struct + mailimap_extension_data * data); + +/* + stores the ext_data in the session (only needed for extensions + that embed directly into response-data). +*/ +void mailimap_extension_data_store(mailimap * session, + struct mailimap_extension_data ** ext_data); + +/* + return 1 if the extension of the given name is supported. + the name is searched in the capabilities. +*/ + +LIBETPAN_EXPORT +int mailimap_has_extension(mailimap * session, char * extension_name); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_extension_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_extension_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,67 @@ +#ifndef MAILIMAP_EXTENSION_TYPES_H + +#define MAILIMAP_EXTENSION_TYPES_H + +/* + this is the list of known extensions with the purpose to + get integer identifers for the extensions. +*/ + +enum { + MAILIMAP_EXTENSION_ANNOTATEMORE, /* the annotatemore-draft */ + MAILIMAP_EXTENSION_ACL, /* the acl capability */ + MAILIMAP_EXTENSION_UIDPLUS, /* UIDPLUS */ +}; + + +/* + this is a list of extended parser functions. The extended parser + passes its identifier to the extension parser. +*/ + +enum { + MAILIMAP_EXTENDED_PARSER_RESPONSE_DATA, + MAILIMAP_EXTENDED_PARSER_RESP_TEXT_CODE, + MAILIMAP_EXTENDED_PARSER_MAILBOX_DATA, +}; + +/* + this is the extension interface. each extension consists + of a initial parser and an initial free. the parser is + passed the calling parser's identifier. based on this + identifier the initial parser can then decide which + actual parser to call. free has mailimap_extension_data + as parameter. if you look at mailimap_extension_data + you'll see that it contains "type" as one of its + elements. thus an extension's initial free can call + the correct actual free to free its data. +*/ +struct mailimap_extension_api { + char * ext_name; + int ext_id; /* use -1 if this is an extension outside libetpan */ + + int (* ext_parser)(int calling_parser, mailstream * fd, + MMAPString * buffer, size_t * index, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + + void (* ext_free)(struct mailimap_extension_data * ext_data); +}; + +/* + mailimap_extension_data is a wrapper for values parsed by extensions + + - extension is an identifier for the extension that parsed the value. + + - type is an identifier for the real type of the data. + + - data is a pointer to the real data. +*/ +struct mailimap_extension_data { + struct mailimap_extension_api * ext_extension; + int ext_type; + void * ext_data; +}; + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_helper.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_helper.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,209 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_helper.c,v 1.12 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimap_helper.h" + +#include <stdlib.h> +#include "mailimap.h" + +int mailimap_fetch_rfc822(mailimap * session, + uint32_t msgid, char ** result) +{ + int r; + clist * fetch_list; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * item; + int res; + + fetch_att = mailimap_fetch_att_new_rfc822(); + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + set = mailimap_set_new_single(msgid); + + r = mailimap_fetch(session, set, fetch_type, &fetch_list); + + mailimap_set_free(set); + mailimap_fetch_type_free(fetch_type); + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (clist_isempty(fetch_list)) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + msg_att = (struct mailimap_msg_att *) clist_begin(fetch_list)->data; + + if (clist_isempty(msg_att->att_list)) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + item = (struct mailimap_msg_att_item *) clist_begin(msg_att->att_list)->data; + + if (item->att_type != MAILIMAP_MSG_ATT_ITEM_STATIC) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + if (item->att_data.att_static->att_type != MAILIMAP_MSG_ATT_RFC822) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + * result = item->att_data.att_static->att_data.att_rfc822.att_content; + item->att_data.att_static->att_data.att_rfc822.att_content = NULL; + mailimap_fetch_list_free(fetch_list); + + return MAILIMAP_NO_ERROR; + +free: + mailimap_fetch_list_free(fetch_list); +err: + return res; +} + +int mailimap_fetch_rfc822_header(mailimap * session, + uint32_t msgid, char ** result) +{ + int r; + int res; + clist * fetch_list; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + struct mailimap_msg_att * msg_att; + struct mailimap_msg_att_item * item; + + fetch_att = mailimap_fetch_att_new_rfc822_header(); + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + set = mailimap_set_new_single(msgid); + + r = mailimap_fetch(session, set, fetch_type, &fetch_list); + + mailimap_set_free(set); + mailimap_fetch_type_free(fetch_type); + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (clist_isempty(fetch_list)) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + msg_att = (struct mailimap_msg_att *) clist_begin(fetch_list)->data; + + if (clist_isempty(msg_att->att_list)) { + res = MAILIMAP_ERROR_FETCH; + goto free; + } + + item = (struct mailimap_msg_att_item *) clist_begin(msg_att->att_list)->data; + + if (item->att_type != MAILIMAP_MSG_ATT_ITEM_STATIC) { + res = MAILIMAP_ERROR_FETCH; + goto err; + } + + if (item->att_data.att_static->att_type != MAILIMAP_MSG_ATT_RFC822_HEADER) { + res = MAILIMAP_ERROR_FETCH; + goto err; + } + + * result = item->att_data.att_static->att_data.att_rfc822_header.att_content; + item->att_data.att_static->att_data.att_rfc822_header.att_content = NULL; + mailimap_fetch_list_free(fetch_list); + + return MAILIMAP_NO_ERROR; + +free: + mailimap_fetch_list_free(fetch_list); +err: + return res; +} + +int mailimap_fetch_envelope(mailimap * session, + uint32_t first, uint32_t last, + clist ** result) +{ + int r; + clist * fetch_list; + struct mailimap_fetch_att * fetch_att; + struct mailimap_fetch_type * fetch_type; + struct mailimap_set * set; + + fetch_att = mailimap_fetch_att_new_envelope(); + fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att); + set = mailimap_set_new_interval(first, last); + + r = mailimap_fetch(session, set, fetch_type, &fetch_list); + + mailimap_set_free(set); + mailimap_fetch_type_free(fetch_type); + + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = fetch_list; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_append_simple(mailimap * session, const char * mailbox, + const char * content, uint32_t size) +{ + return mailimap_append(session, mailbox, NULL, NULL, content, size); +} + +int mailimap_login_simple(mailimap * session, + const char * userid, const char * password) +{ + if (session->imap_state == MAILIMAP_STATE_NON_AUTHENTICATED) + return mailimap_login(session, userid, password); + else + return MAILIMAP_NO_ERROR; +} + Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_helper.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_helper.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,66 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_helper.h,v 1.12 2006/06/07 15:10:01 smarinier Exp $ + */ + +#ifndef MAILIMAP_HELPER_H + +#define MAILIMAP_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailimap_types.h> + +int mailimap_fetch_rfc822(mailimap * session, + uint32_t msgid, char ** result); + +int mailimap_fetch_rfc822_header(mailimap * session, + uint32_t msgid, char ** result); + +int mailimap_fetch_envelope(mailimap * session, + uint32_t first, uint32_t last, + clist ** result); + +int mailimap_append_simple(mailimap * session, const char * mailbox, + const char * content, uint32_t size); + +int mailimap_login_simple(mailimap * session, + const char * userid, const char * password); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_keywords.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_keywords.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,357 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_keywords.c,v 1.12 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimap_keywords.h" +#include "mailimap_types.h" +#include <string.h> +#include <stdio.h> + +#ifndef UNSTRICT_SYNTAX +#define UNSTRICT_SYNTAX +#endif + +struct mailimap_token_value { + int value; + const char * str; +}; + +int mailimap_token_case_insensitive_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + const char * token) +{ + int len; + size_t cur_token; + int r; + + cur_token = * index; + len = strlen(token); + +#ifdef UNSTRICT_SYNTAX + r = mailimap_space_parse(fd, buffer, &cur_token); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; +#endif + + if (strncasecmp(buffer->str + cur_token, token, len) == 0) { + cur_token += len; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + + +static int is_space_or_tab(char ch) +{ + return (ch == ' ') || (ch == '\t'); +} + +int mailimap_char_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char token) +{ + int cur_token; + + cur_token = * index; + + if (buffer->str[cur_token] == token) { + cur_token ++; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + +int mailimap_space_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ +#ifdef UNSTRICT_SYNTAX + + /* can accept unstrict syntax */ + size_t cur_token; + + cur_token = * index; + + while (is_space_or_tab(* (buffer->str + cur_token))) + cur_token ++; + + if (cur_token == * index) + return MAILIMAP_ERROR_PARSE; + + * index = cur_token; + + return MAILIMAP_NO_ERROR; + +#else + return mailimap_char_parse(fd, buffer, index, ' '); +#endif +} + + + +#define mailimap_get_token_str(index, tab) \ + mailimap_get_token_str_size(index, tab, \ + sizeof(tab) / sizeof(struct mailimap_token_value)) + +#define mailimap_get_token_value(fd, buffer, index, tab) \ + mailimap_get_token_value_size(fd, buffer, index, tab, \ + sizeof(tab) / sizeof(struct mailimap_token_value)) + + +static const char * mailimap_get_token_str_size(int index, + struct mailimap_token_value * tab, + size_t size) +{ + size_t i; + + for(i = 0 ; i < size ; i++) + if (index == tab[i].value) + return tab[i].str; + + return NULL; +} + + + +static int mailimap_get_token_value_size(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_token_value * tab, + size_t size) +{ + size_t i; + int r; + +#ifdef UNSTRICT_SYNTAX + /* can accept unstrict syntax */ + r = mailimap_space_parse(fd, buffer, index); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; +#endif + + for(i = 0 ; i < size ; i++) { + r = mailimap_token_case_insensitive_parse(fd, buffer, index, tab[i].str); + if (r == MAILIMAP_NO_ERROR) + return tab[i].value; + } + + return -1; +} + + +static struct mailimap_token_value status_att_tab[] = { + {MAILIMAP_STATUS_ATT_MESSAGES, "MESSAGES"}, + {MAILIMAP_STATUS_ATT_RECENT, "RECENT"}, + {MAILIMAP_STATUS_ATT_UIDNEXT, "UIDNEXT"}, + {MAILIMAP_STATUS_ATT_UIDVALIDITY, "UIDVALIDITY"}, + {MAILIMAP_STATUS_ATT_UNSEEN, "UNSEEN"} +}; + +int mailimap_status_att_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + int r; + +#ifdef UNSTRICT_SYNTAX + /* can accept unstrict syntax */ + r = mailimap_space_parse(fd, buffer, index); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; +#endif + return mailimap_get_token_value(fd, buffer, index, + status_att_tab); +} + + +const char * mailimap_status_att_get_token_str(size_t index) +{ + return mailimap_get_token_str(index, status_att_tab); +} + +static struct mailimap_token_value month_tab[] = { + {1, "Jan"}, + {2, "Feb"}, + {3, "Mar"}, + {4, "Apr"}, + {5, "May"}, + {6, "Jun"}, + {7, "Jul"}, + {8, "Aug"}, + {9, "Sep"}, + {10, "Oct"}, + {11, "Nov"}, + {12, "Dec"} +}; + +int mailimap_month_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, month_tab); +} + + +const char * mailimap_month_get_token_str(size_t index) +{ + return mailimap_get_token_str(index, month_tab); +} + + + + + +static struct mailimap_token_value mailimap_flag_tab[] = { + {MAILIMAP_FLAG_ANSWERED, "\\Answered"}, + {MAILIMAP_FLAG_FLAGGED, "\\Flagged"}, + {MAILIMAP_FLAG_DELETED, "\\Deleted"}, + {MAILIMAP_FLAG_SEEN, "\\Seen"}, + {MAILIMAP_FLAG_DRAFT, "\\Draft"} +}; + +int mailimap_flag_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, + mailimap_flag_tab); +} + + +const char * mailimap_flag_get_token_str(size_t index) +{ + return mailimap_get_token_str(index, mailimap_flag_tab); +} + + + + +static struct mailimap_token_value encoding_tab[] = { + {MAILIMAP_BODY_FLD_ENC_7BIT, "7BIT"}, + {MAILIMAP_BODY_FLD_ENC_8BIT, "8BIT"}, + {MAILIMAP_BODY_FLD_ENC_BINARY, "BINARY"}, + {MAILIMAP_BODY_FLD_ENC_BASE64, "BASE64"}, + {MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE, "QUOTED-PRINTABLE"} +}; + +int mailimap_encoding_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, encoding_tab); +} + +static struct mailimap_token_value mbx_list_sflag_tab[] = { + {MAILIMAP_MBX_LIST_SFLAG_MARKED, "\\Marked"}, + {MAILIMAP_MBX_LIST_SFLAG_NOSELECT, "\\Noselect"}, + {MAILIMAP_MBX_LIST_SFLAG_UNMARKED, "\\Unmarked"} +}; + +int mailimap_mbx_list_sflag_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, mbx_list_sflag_tab); +} + +static struct mailimap_token_value media_basic_tab[] = { + {MAILIMAP_MEDIA_BASIC_APPLICATION, "APPLICATION"}, + {MAILIMAP_MEDIA_BASIC_AUDIO, "AUDIO"}, + {MAILIMAP_MEDIA_BASIC_IMAGE, "IMAGE"}, + {MAILIMAP_MEDIA_BASIC_MESSAGE, "MESSAGE"}, + {MAILIMAP_MEDIA_BASIC_VIDEO, "VIDEO"} +}; + +int mailimap_media_basic_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, media_basic_tab); +} + +static struct mailimap_token_value resp_cond_state_tab[] = { + {MAILIMAP_RESP_COND_STATE_OK, "OK"}, + {MAILIMAP_RESP_COND_STATE_NO, "NO"}, + {MAILIMAP_RESP_COND_STATE_BAD, "BAD"} +}; + +int mailimap_resp_cond_state_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, resp_cond_state_tab); +} + +static struct mailimap_token_value resp_text_code_1_tab[] = { + {MAILIMAP_RESP_TEXT_CODE_ALERT, "ALERT"}, + {MAILIMAP_RESP_TEXT_CODE_PARSE, "PARSE"}, + {MAILIMAP_RESP_TEXT_CODE_READ_ONLY, "READ-ONLY"}, + {MAILIMAP_RESP_TEXT_CODE_READ_WRITE, "READ-WRITE"}, + {MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, "TRYCREATE"} +}; + +int mailimap_resp_text_code_1_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, resp_text_code_1_tab); +} + +static struct mailimap_token_value resp_text_code_2_tab[] = { + {MAILIMAP_RESP_TEXT_CODE_UIDNEXT, "UIDNEXT"}, + {MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, "UIDVALIDITY"}, + {MAILIMAP_RESP_TEXT_CODE_UNSEEN, "UNSEEN"}, +}; + +int mailimap_resp_text_code_2_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, resp_text_code_2_tab); +} + +static struct mailimap_token_value section_msgtext_tab[] = { + {MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, "HEADER.FIELDS.NOT"}, + {MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, "HEADER.FIELDS"}, + {MAILIMAP_SECTION_MSGTEXT_HEADER, "HEADER"}, + {MAILIMAP_SECTION_MSGTEXT_TEXT, "TEXT"} +}; + +int mailimap_section_msgtext_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index) +{ + return mailimap_get_token_value(fd, buffer, index, section_msgtext_tab); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_keywords.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_keywords.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,107 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_keywords.h,v 1.8 2004/11/21 21:53:36 hoa Exp $ + */ + +#ifndef MAILIMAP_COMMON_H + +#define MAILIMAP_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailstream.h" + + +/* tools */ + +int mailimap_char_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char token); + +int mailimap_space_parse(mailstream * fd, MMAPString * buffer, + size_t * index); + +/* tokens */ + +int mailimap_token_case_insensitive_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + const char * token); + +int mailimap_status_att_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index); +const char * mailimap_status_att_get_token_str(size_t index); + + +int mailimap_month_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index); +const char * mailimap_month_get_token_str(size_t index); + + +int mailimap_flag_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index); + +const char * mailimap_flag_get_token_str(size_t index); + +int mailimap_encoding_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index); + +int mailimap_mbx_list_sflag_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index); + +int mailimap_media_basic_get_token_value(mailstream * fd, MMAPString * buffer, + size_t * index); + +int mailimap_resp_cond_state_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index); + +int mailimap_resp_text_code_1_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index); + +int mailimap_resp_text_code_2_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index); + +int mailimap_section_msgtext_get_token_value(mailstream * fd, + MMAPString * buffer, + size_t * index); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_parser.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_parser.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,9528 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_parser.c,v 1.34 2006/10/20 00:13:30 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#include "mailstream.h" +#include "mailimap_keywords.h" +#include "mailimap_parser.h" +#include "mailimap_extension.h" +#include "mmapstring.h" +#include "mail.h" + +#ifndef UNSTRICT_SYNTAX +#define UNSTRICT_SYNTAX +#endif + +/* + Document: internet-drafts/draft-crispin-imapv-15.txt + RFC 2060 (IMAP but rather used draft) + RFC 2234 for all token that are not defined such as ALPHA +*/ + + + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + +static int mailimap_address_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_address ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_addr_adl_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_addr_host_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_addr_mailbox_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_addr_name_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_atom_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_auth_type_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_base64_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_body_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_body_extension_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_extension ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_body_ext_1part_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_ext_1part ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_ext_mpart_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_ext_mpart ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_body_fields_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fields ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_body_fld_desc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_body_fld_dsp_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_dsp ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_fld_enc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_enc ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int mailimap_body_fld_id_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_body_fld_lang_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_lang ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_body_fld_lines_parse(mailstream * fd, + MMAPString * buffer, size_t * index, + uint32_t * result); + +static int mailimap_body_fld_md5_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_body_fld_octets_parse(mailstream * fd, + MMAPString * buffer, size_t * index, + uint32_t * result); + +static int +mailimap_body_fld_param_parse(mailstream * fd, + MMAPString * buffer, size_t * index, + struct mailimap_body_fld_param ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_type_1part_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_1part ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_type_basic_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_basic ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_type_mpart_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + struct mailimap_body_type_mpart ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_type_msg_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_msg ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_body_type_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_text ** + result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_capability_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_capability ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_capability_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_capability_data ** result, + size_t progr_rate, + progress_function * progr_fun); + + +/* +static gboolean mailimap_date_day_parse(mailstream * fd, + MMAPString * buffer, + guint32 * index, + gint * result); +*/ +static int mailimap_date_day_fixed_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + int * result); + +static int mailimap_date_month_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result); + +/* +struct mailimap_date_text { + gint day; + gint month; + gint year; +}; + +static gboolean +mailimap_date_text_parse(mailstream * fd, MMAPString * buffer, + guint32 * index, struct mailimap_date_text ** result); +static void mailimap_date_text_free(struct mailimap_date_text * date_text); +*/ + +static int mailimap_date_year_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result); + +static int mailimap_date_time_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_date_time ** t, + size_t progr_rate, + progress_function * progr_fun); + +#ifndef UNSTRICT_SYNTAX +static int mailimap_digit_nz_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result); +#endif + + +static int mailimap_envelope_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_envelope ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_env_bcc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_bcc ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_env_cc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_cc ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_env_date_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_env_from_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_from ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int mailimap_env_in_reply_to_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_env_message_id_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_env_reply_to_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_env_reply_to ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_env_sender_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_sender ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_env_subject_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_env_to_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_env_to ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int mailimap_flag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_flag_extension_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + + + + +static int +mailimap_flag_fetch_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag_fetch ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_flag_perm_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag_perm ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int mailimap_flag_keyword_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int mailimap_flag_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag_list ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_header_fld_name_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + + + + +static int +mailimap_header_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_header_list ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_literal_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_mailbox_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mailbox_data ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_mbx_list_flags_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mbx_list_flags ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_mbx_list_oflag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mbx_list_oflag ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_mbx_list_oflag_no_sflag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mbx_list_oflag ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_mbx_list_sflag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + int * result); + + +static int +mailimap_mailbox_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mailbox_list ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_media_basic_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_media_basic ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_media_message_parse(mailstream * fd, MMAPString * buffer, + size_t * index); + +static int +mailimap_media_subtype_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_media_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_message_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_message_data ** result, + size_t progr_rate, + progress_function * progr_fun); + + + + + +static int +mailimap_msg_att_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_msg_att ** result, + size_t progr_rate, + progress_function * progr_fun); + + + +static int +mailimap_msg_att_dynamic_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_msg_att_dynamic ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_msg_att_static_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_msg_att_static ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_nil_parse(mailstream * fd, MMAPString * buffer, + size_t * index); + +static int +mailimap_number_parse(mailstream * fd, MMAPString * buffer, + size_t * index, uint32_t * result); + +static int +mailimap_quoted_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_quoted_char_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char * result); + + +static int +mailimap_quoted_specials_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char * result); + + + + + +static int +mailimap_response_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_data ** result, + size_t progr_rate, + progress_function * progr_fun); + + + + +static int +mailimap_response_done_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_done ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_response_fatal_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_fatal ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_response_tagged_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_tagged ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_resp_cond_auth_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_cond_auth ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int +mailimap_resp_cond_bye_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_cond_bye ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_resp_cond_state_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_cond_state ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_resp_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_text ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_resp_text_code_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_text_code ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_section_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_section_msgtext_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_msgtext ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_section_part_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_part ** result, + size_t progr_rate, + progress_function * progr_fun); + + + + +static int +mailimap_section_spec_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_spec ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int +mailimap_section_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_text ** result, + size_t progr_rate, + progress_function * progr_fun); + + +static int mailimap_status_att_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result); + +static int mailimap_tag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +static int mailimap_time_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + int * phour, int * pmin, int * psec); + +static int mailimap_zone_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result); + + + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + + +/* ******************** TOOLS **************************** */ + + +static int mailimap_unstrict_char_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char token) +{ + size_t cur_token; + int r; + + cur_token = * index; + +#ifdef UNSTRICT_SYNTAX + /* can accept unstrict syntax */ + + mailimap_space_parse(fd, buffer, &cur_token); + if (token == ' ') { + * index = cur_token; + return MAILIMAP_NO_ERROR; + } +#endif + + r = mailimap_char_parse(fd, buffer, &cur_token, token); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_oparenth_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '('); +} + +int mailimap_cparenth_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, ')'); +} + +static int mailimap_oaccolade_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '{'); +} + +static int mailimap_caccolade_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '}'); +} + +static int mailimap_plus_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '+'); +} + +static int mailimap_minus_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '-'); +} + +static int mailimap_star_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '*'); +} + +static int mailimap_dot_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '.'); +} + +int mailimap_colon_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, ':'); +} + +static int mailimap_lower_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '<'); +} + +static int mailimap_greater_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '>'); +} + +static int mailimap_obracket_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, '['); +} + +static int mailimap_cbracket_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_unstrict_char_parse(fd, buffer, index, ']'); +} + +static int mailimap_dquote_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_char_parse(fd, buffer, index, '\"'); +} + +static int mailimap_crlf_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + size_t cur_token = * index; + +#ifdef UNSTRICT_SYNTAX + mailimap_space_parse(fd, buffer, &cur_token); +#endif + + if (mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "\r\n")) { + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + +#ifdef UNSTRICT_SYNTAX + else if (mailimap_unstrict_char_parse(fd, buffer, &cur_token, '\n')) { + * index = cur_token; + return MAILIMAP_NO_ERROR; + } +#endif + + else + return MAILIMAP_ERROR_PARSE; +} + +static int +mailimap_struct_multiple_parse(mailstream * fd, MMAPString * buffer, + size_t * index, clist ** result, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * struct_list; + size_t cur_token; + void * value; + int r; + int res; + + cur_token = * index; + + r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + while (1) { + r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) + break; + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + } + + * result = struct_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_list: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); + err: + return res; +} + +int +mailimap_struct_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, clist ** result, + char symbol, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * struct_list; + size_t cur_token; + void * value; + size_t final_token; + int r; + int res; + + cur_token = * index; + struct_list = NULL; + + r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + + while (1) { + r = mailimap_unstrict_char_parse(fd, buffer, &cur_token, symbol); + if (r == MAILIMAP_ERROR_PARSE) + break; + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + r = parser(fd, buffer, &cur_token, &value, progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) + break; + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + } + + * result = struct_list; + * index = final_token; + + return MAILIMAP_NO_ERROR; + + free_list: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); + err: + return res; +} + +int +mailimap_struct_spaced_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, clist ** result, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_struct_list_parse(fd, buffer, index, result, + ' ', parser, destructor, + progr_rate, progr_fun); +} + + + +static int +mailimap_custom_string_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + int (* is_custom_char)(char)) +{ + size_t begin; + size_t end; + char * gstr; + + begin = * index; + +#ifdef UNSTRICT_SYNTAX + mailimap_space_parse(fd, buffer, &begin); +#endif + + end = begin; + + while (is_custom_char(buffer->str[end])) + end ++; + + if (end != begin) { + gstr = malloc(end - begin + 1); + if (gstr == NULL) + return MAILIMAP_ERROR_MEMORY; + + strncpy(gstr, buffer->str + begin, end - begin); + gstr[end - begin] = '\0'; + + * index = end; + * result = gstr; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + + + +static int +mailimap_nz_number_alloc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + uint32_t ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + uint32_t number; + uint32_t * number_alloc; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimap_nz_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + number_alloc = mailimap_number_alloc_new(number); + if (number_alloc == NULL) + return MAILIMAP_ERROR_MEMORY; + + * index = cur_token; + * result = number_alloc; + + return MAILIMAP_NO_ERROR; +} + + +static int is_ctl(char ch) +{ + unsigned char uch = (unsigned char) ch; + + return (uch <= 0x1F); +} + +static int is_char(char ch) +{ +#ifdef UNSTRICT_SYNTAX + return (ch != 0); +#else + unsigned char uch = ch; + + return (uch >= 0x01) && (uch <= 0x7f); +#endif +} + +static int is_alpha(char ch) +{ + return ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && (ch <= 'z'))); +} + +static int is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + +static int mailimap_digit_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result) +{ + size_t cur_token; + + cur_token = * index; + + if (is_digit(buffer->str[cur_token])) { + * result = buffer->str[cur_token] - '0'; + cur_token ++; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + + +/* ******************** parser **************************** */ + +/* + address = "(" addr-name SP addr-adl SP addr-mailbox SP + addr-host ")" +*/ + +static int mailimap_address_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_address ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * addr_name; + char * addr_adl; + char * addr_mailbox; + char * addr_host; + struct mailimap_address * addr; + int r; + int res; + + cur_token = * index; + + addr_name = NULL; + addr_adl = NULL; + addr_mailbox = NULL; + addr_host = NULL; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_addr_name_parse(fd, buffer, &cur_token, &addr_name, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_name_free; + } + + r = mailimap_addr_adl_parse(fd, buffer, &cur_token, &addr_adl, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_name_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_adl_free; + } + + r = mailimap_addr_mailbox_parse(fd, buffer, &cur_token, &addr_mailbox, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_adl_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_mailbox_free; + } + + r = mailimap_addr_host_parse(fd, buffer, &cur_token, &addr_host, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_mailbox_free; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto addr_host_free; + } + + addr = mailimap_address_new(addr_name, addr_adl, addr_mailbox, addr_host); + + if (addr == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto addr_host_free; + } + + * result = addr; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + addr_host_free: + mailimap_addr_host_free(addr_host); + addr_mailbox_free: + mailimap_addr_mailbox_free(addr_mailbox); + addr_adl_free: + mailimap_addr_adl_free(addr_adl); + addr_name_free: + mailimap_addr_name_free(addr_name); + err: + return res; +} + +/* + addr-adl = nstring + ; Holds route from [RFC-822] route-addr if + ; non-NIL +*/ + +static int mailimap_addr_adl_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + addr-host = nstring + ; NIL indicates [RFC-822] group syntax. + ; Otherwise, holds [RFC-822] domain name +*/ + +static int mailimap_addr_host_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + addr-mailbox = nstring + ; NIL indicates end of [RFC-822] group; if + ; non-NIL and addr-host is NIL, holds + ; [RFC-822] group name. + ; Otherwise, holds [RFC-822] local-part + ; after removing [RFC-822] quoting + */ + +static int mailimap_addr_mailbox_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + + +/* + addr-name = nstring + ; If non-NIL, holds phrase from [RFC-822] + ; mailbox after removing [RFC-822] quoting +*/ + +static int mailimap_addr_name_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + + +/* + NOT IMPLEMENTED + append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP + literal +*/ + +/* + astring = 1*ASTRING-CHAR / string +*/ + +static int is_astring_char(char ch); + +static int +mailimap_atom_astring_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_custom_string_parse(fd, buffer, index, result, + is_astring_char); +} + +int +mailimap_astring_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * astring; + int r; + + cur_token = * index; + + r = mailimap_atom_astring_parse(fd, buffer, &cur_token, &astring, + progr_rate, progr_fun); + switch (r) { + case MAILIMAP_NO_ERROR: + break; + + case MAILIMAP_ERROR_PARSE: + r = mailimap_string_parse(fd, buffer, &cur_token, &astring, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + break; + + default: + return r; + } + + * result = astring; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + ASTRING-CHAR = ATOM-CHAR / resp-specials +*/ + +static int is_atom_char(char ch); +static int is_resp_specials(char ch); + +static int is_astring_char(char ch) +{ + if (is_atom_char(ch)) + return TRUE; + if (is_resp_specials(ch)) + return TRUE; + return FALSE; +} + +/* + atom = 1*ATOM-CHAR +*/ + +static int mailimap_atom_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_custom_string_parse(fd, buffer, index, result, + is_atom_char); +} + +/* + ATOM-CHAR = <any CHAR except atom-specials> +*/ + +static int is_atom_specials(char ch); + +static int is_atom_char(char ch) +{ + if (is_atom_specials(ch)) + return FALSE; + + return is_char(ch); +} + +/* + atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / + quoted-specials / resp-specials + +no "}" because there is no need (Mark Crispin) +*/ + +static int is_quoted_specials(char ch); +static int is_list_wildcards(char ch); + +static int is_atom_specials(char ch) +{ + switch (ch) { + case '(': + case ')': + case '{': + case ' ': + return TRUE; + }; + if (is_ctl(ch)) + return TRUE; + if (is_list_wildcards(ch)) + return TRUE; + if (is_resp_specials(ch)) + return TRUE; + + return is_quoted_specials(ch); +} + +/* + NOT IMPLEMENTED + authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64) +*/ + +/* + auth-type = atom + ; Defined by [SASL] +*/ + +static int mailimap_auth_type_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_atom_parse(fd, buffer, index, result, + progr_rate, progr_fun); +} + +/* + base64 = *(4base64-char) [base64-terminal] +*/ + +static int is_base64_4char(char * str); +static int is_base64_terminal(char * str); + +static int mailimap_base64_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t begin; + size_t end; + char * gstr; + + begin = * index; + end = begin; + + while (is_base64_4char(buffer->str + end)) + end += 4; + if (is_base64_terminal(buffer->str + end)) + end += 4; +#if 0 + else + return MAILIMAP_ERROR_PARSE; +#endif + + gstr = malloc(end - begin + 1); + if (gstr == NULL) + return MAILIMAP_ERROR_MEMORY; + strncpy(gstr, buffer->str + begin, end - begin); + gstr[end - begin] = '\0'; + + * result = gstr; + * index = end; + + return MAILIMAP_NO_ERROR; +} + +/* + base64-char = ALPHA / DIGIT / "+" / "/" + ; Case-sensitive +*/ + +static int is_base64_char(char ch) +{ + return (is_alpha(ch) || is_digit(ch) || ch == '+' || ch == '/'); +} + +static int is_base64_4char(char * str) +{ + size_t i; + + for (i = 0 ; i < 4 ; i++) + if (!is_base64_char(str[i])) + return FALSE; + return TRUE; +} + +/* + base64-terminal = (2base64-char "==") / (3base64-char "=") +*/ + +static int is_base64_terminal(char * str) +{ + if (str[0] == 0) + return FALSE; + if (str[1] == 0) + return FALSE; + if (str[2] == 0) + return FALSE; + if (str[3] == 0) + return FALSE; + + if (is_base64_char(str[0]) || is_base64_char(str[1]) + || str[2] == '=' || str[3] == '=') + return TRUE; + if (is_base64_char(str[0]) || is_base64_char(str[1]) + || is_base64_char(str[2]) || str[3] == '=') + return TRUE; + return FALSE; +} + + +/* + body = "(" (body-type-1part / body-type-mpart) ")" +*/ + +static int mailimap_body_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body_type_1part * body_type_1part; + struct mailimap_body_type_mpart * body_type_mpart; + struct mailimap_body * body; + size_t cur_token; + int type; + int r; + int res; + + cur_token = * index; + + body_type_1part = NULL; + body_type_mpart = NULL; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_BODY_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_body_type_1part_parse(fd, buffer, &cur_token, &body_type_1part, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_1PART; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_body_type_mpart_parse(fd, buffer, &cur_token, + &body_type_mpart, + progr_rate, progr_fun); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_MPART; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + body = mailimap_body_new(type, body_type_1part, body_type_mpart); + if (body == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = body; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (body_type_1part) + mailimap_body_type_1part_free(body_type_1part); + if (body_type_mpart) + mailimap_body_type_mpart_free(body_type_mpart); + err: + return res; +} + +/* + body-extension = nstring / number / + "(" body-extension *(SP body-extension) ")" + ; Future expansion. Client implementations + ; MUST accept body-extension fields. Server + ; implementations MUST NOT generate + ; body-extension fields except as defined by + ; future standard or standards-track + ; revisions of this specification. +*/ + +/* + "(" body-extension *(SP body-extension) ")" +*/ + +static int +mailimap_body_ext_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * list; + int r; + int res; + + cur_token = * index; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, + &cur_token, &list, + (mailimap_struct_parser * ) + mailimap_body_extension_parse, + (mailimap_struct_destructor * ) + mailimap_body_extension_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + * index = cur_token; + * result = list; + + return MAILIMAP_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimap_body_extension_free, NULL); + clist_free(list); + err: + return res; +} + +/* + body-extension = nstring / number / + "(" body-extension *(SP body-extension) ")" + ; Future expansion. Client implementations + ; MUST accept body-extension fields. Server + ; implementations MUST NOT generate + ; body-extension fields except as defined by + ; future standard or standards-track + ; revisions of this specification. +*/ + +static int +mailimap_body_extension_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_extension ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + uint32_t number; + char * nstring; + clist * body_extension_list; + struct mailimap_body_extension * body_extension; + int type; + int r; + int res; + + cur_token = * index; + + nstring = NULL; + number = 0; + body_extension_list = NULL; + type = MAILIMAP_BODY_EXTENSION_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_nstring_parse(fd, buffer, &cur_token, &nstring, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_EXTENSION_NSTRING; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_EXTENSION_NUMBER; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_body_ext_list_parse(fd, buffer, &cur_token, + &body_extension_list, + progr_rate, progr_fun); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_EXTENSION_LIST; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + body_extension = mailimap_body_extension_new(type, nstring, number, + body_extension_list); + + if (body_extension == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = body_extension; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (nstring != NULL) + mailimap_nstring_free(nstring); + if (body_extension_list) { + clist_foreach(body_extension_list, + (clist_func) mailimap_body_extension_free, + NULL); + clist_free(body_extension_list); + } + err: + return res; +} + +/* + body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch +*/ + +/* + *(SP body-extension) +*/ + +static int +mailimap_body_ext_1part_3_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + clist ** body_ext_list, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int r; + + cur_token = * index; + * body_ext_list = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, + body_ext_list, + (mailimap_struct_parser *) + mailimap_body_extension_parse, + (mailimap_struct_destructor *) + mailimap_body_extension_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + [SP body-fld-lang + *(SP body-extension)]] +*/ + +static int +mailimap_body_ext_1part_2_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_lang ** fld_lang, + clist ** body_ext_list, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int r; + + cur_token = * index; + * fld_lang = NULL; + * body_ext_list = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_fld_lang_parse(fd, buffer, &cur_token, fld_lang, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_ext_1part_3_parse(fd, buffer, &cur_token, + body_ext_list, progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] +*/ + +static int +mailimap_body_ext_1part_1_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_dsp ** fld_dsp, + struct mailimap_body_fld_lang ** fld_lang, + clist ** body_ext_list, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int r; + + cur_token = * index; + * fld_dsp = NULL; + * fld_lang = NULL; + * body_ext_list = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_fld_dsp_parse(fd, buffer, &cur_token, fld_dsp, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_ext_1part_2_parse(fd, buffer, &cur_token, + fld_lang, body_ext_list, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch +*/ + +static int +mailimap_body_ext_1part_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_ext_1part ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + + char * fld_md5; + struct mailimap_body_fld_dsp * fld_dsp; + struct mailimap_body_fld_lang * fld_lang; + clist * body_ext_list; + int r; + int res; + + struct mailimap_body_ext_1part * ext_1part; + + cur_token = * index; + + fld_md5 = NULL; + fld_dsp = NULL; + fld_lang = NULL; + body_ext_list = NULL; + + r = mailimap_body_fld_md5_parse(fd, buffer, &cur_token, &fld_md5, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_body_ext_1part_1_parse(fd, buffer, &cur_token, + &fld_dsp, + &fld_lang, + &body_ext_list, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto free; + } + + ext_1part = mailimap_body_ext_1part_new(fld_md5, fld_dsp, fld_lang, + body_ext_list); + + if (ext_1part == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = ext_1part; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (body_ext_list) { + clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free, + NULL); + clist_free(body_ext_list); + } + if (fld_lang) + mailimap_body_fld_lang_free(fld_lang); + if (fld_dsp) + mailimap_body_fld_dsp_free(fld_dsp); + mailimap_body_fld_md5_free(fld_md5); + err: + return res; +} + + +/* + body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch +*/ + +static int +mailimap_body_ext_mpart_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_ext_mpart ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + + struct mailimap_body_fld_dsp * fld_dsp; + struct mailimap_body_fld_lang * fld_lang; + struct mailimap_body_fld_param * fld_param; + clist * body_ext_list; + + struct mailimap_body_ext_mpart * ext_mpart; + int r; + int res; + + cur_token = * index; + + fld_param = NULL; + fld_dsp = NULL; + fld_lang = NULL; + body_ext_list = NULL; + + r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, &fld_param, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_body_ext_1part_1_parse(fd, buffer, &cur_token, + &fld_dsp, + &fld_lang, + &body_ext_list, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto free; + } + + ext_mpart = mailimap_body_ext_mpart_new(fld_param, fld_dsp, fld_lang, + body_ext_list); + if (ext_mpart == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = ext_mpart; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (body_ext_list) { + clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free, + NULL); + clist_free(body_ext_list); + } + if (fld_lang) + mailimap_body_fld_lang_free(fld_lang); + if (fld_dsp) + mailimap_body_fld_dsp_free(fld_dsp); + if (fld_param != NULL) + mailimap_body_fld_param_free(fld_param); + err: + return res; +} + +/* + body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP + body-fld-enc SP body-fld-octets +*/ + +static int +mailimap_body_fields_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fields ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body_fields * body_fields; + size_t cur_token; + struct mailimap_body_fld_param * body_fld_param; + char * body_fld_id; + char * body_fld_desc; + struct mailimap_body_fld_enc * body_fld_enc; + uint32_t body_fld_octets; + int r; + int res; + + body_fld_param = NULL; + body_fld_id = NULL; + body_fld_desc = NULL; + body_fld_enc = NULL; + body_fld_octets = 0; + + cur_token = * index; + + r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, &body_fld_param, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_param_free; + } + + r = mailimap_body_fld_id_parse(fd, buffer, &cur_token, &body_fld_id, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_param_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_id_free; + } + + r = mailimap_body_fld_desc_parse(fd, buffer, &cur_token, &body_fld_desc, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_id_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_desc_free; + } + + r = mailimap_body_fld_enc_parse(fd, buffer, &cur_token, &body_fld_enc, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_desc_free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_enc_free; + } + + r = mailimap_body_fld_octets_parse(fd, buffer, &cur_token, + &body_fld_octets); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto fld_enc_free; + } + + body_fields = mailimap_body_fields_new(body_fld_param, + body_fld_id, + body_fld_desc, + body_fld_enc, + body_fld_octets); + if (body_fields == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto fld_enc_free; + } + + * result = body_fields; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + fld_enc_free: + mailimap_body_fld_enc_free(body_fld_enc); + fld_desc_free: + mailimap_body_fld_desc_free(body_fld_desc); + fld_id_free: + mailimap_body_fld_id_free(body_fld_id); + fld_param_free: + if (body_fld_param != NULL) + mailimap_body_fld_param_free(body_fld_param); + err: + return res; +} + +/* + body-fld-desc = nstring +*/ + +static int mailimap_body_fld_desc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + body-fld-dsp = "(" string SP body-fld-param ")" / nil +*/ + +static int +mailimap_body_fld_dsp_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_dsp ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * name; + struct mailimap_body_fld_param * body_fld_param; + struct mailimap_body_fld_dsp * body_fld_dsp; + int res; + int r; + + cur_token = * index; + name = NULL; + body_fld_param = NULL; + + r = mailimap_nil_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + * result = NULL; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + + if (r != MAILIMAP_ERROR_PARSE) { + res = r; + goto err; + } + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_string_parse(fd, buffer, &cur_token, &name, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto string_free; + } + + r = mailimap_body_fld_param_parse(fd, buffer, &cur_token, + &body_fld_param, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto string_free; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto string_free; + } + + body_fld_dsp = mailimap_body_fld_dsp_new(name, body_fld_param); + if (body_fld_dsp == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto fld_param_free; + } + + * index = cur_token; + * result = body_fld_dsp; + + return MAILIMAP_NO_ERROR; + + fld_param_free: + if (body_fld_param != NULL) + mailimap_body_fld_param_free(body_fld_param); + string_free: + mailimap_string_free(name); + err: + return res; +} + +/* + body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ + "QUOTED-PRINTABLE") DQUOTE) / string +*/ + +static inline int +mailimap_body_fld_known_enc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + int * result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + int r; + int res; + + cur_token = * index; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = mailimap_encoding_get_token_value(fd, buffer, &cur_token); + + if (type == -1) { + res = MAILIMAP_ERROR_PARSE; + goto err; + } + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + * result = type; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + err: + return res; +} + +static int +mailimap_body_fld_enc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_enc ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + char * value; + struct mailimap_body_fld_enc * body_fld_enc; + int r; + int res; + + cur_token = * index; + + r = mailimap_body_fld_known_enc_parse(fd, buffer, &cur_token, + &type, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + value = NULL; + } + else if (r == MAILIMAP_ERROR_PARSE) { + type = MAILIMAP_BODY_FLD_ENC_OTHER; + + r = mailimap_string_parse(fd, buffer, &cur_token, &value, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + } + else { + res = r; + goto err; + } + + body_fld_enc = mailimap_body_fld_enc_new(type, value); + if (body_fld_enc == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto value_free; + } + + * result = body_fld_enc; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + value_free: + if (value) + mailimap_string_free(value); + err: + return res; +} + +/* + body-fld-id = nstring +*/ + +static int mailimap_body_fld_id_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + + +/* + body-fld-lang = nstring / "(" string *(SP string) ")" +*/ + +/* +"(" string *(SP string) ")" +*/ + +static int +mailimap_body_fld_lang_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * list; + int r; + int res; + + cur_token = * index; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + while (1) { + char * elt; + + r = mailimap_string_parse(fd, buffer, &cur_token, &elt, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_ERROR_PARSE) + break; + else if (r == MAILIMAP_NO_ERROR) { + r = clist_append(list, elt); + if (r < 0) { + mailimap_string_free(elt); + res = r; + goto list_free; + } + } + else { + res = r; + goto list_free; + } + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto list_free; + } + + * index = cur_token; + * result = list; + + return MAILIMAP_NO_ERROR; + + list_free: + clist_foreach(list, (clist_func) mailimap_string_free, NULL); + clist_free(list); + err: + return res; +} + +/* + body-fld-lang = nstring / "(" string *(SP string) ")" +*/ + +static int +mailimap_body_fld_lang_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_fld_lang ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + char * value; + clist * list; + struct mailimap_body_fld_lang * fld_lang; + int type; + int r; + int res; + + size_t cur_token; + + cur_token = * index; + + value = NULL; + list = NULL; + type = MAILIMAP_BODY_FLD_LANG_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_nstring_parse(fd, buffer, &cur_token, &value, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_FLD_LANG_SINGLE; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_body_fld_lang_list_parse(fd, buffer, &cur_token, &list, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_FLD_LANG_LIST; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + fld_lang = mailimap_body_fld_lang_new(type, value, list); + if (fld_lang == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = fld_lang; + + return MAILIMAP_NO_ERROR; + + free: + if (value) + mailimap_nstring_free(value); + if (list) { + clist_foreach(list, (clist_func) mailimap_string_free, NULL); + clist_free(list); + } + err: + return res; +} + +/* + body-fld-lines = number +*/ + +static int mailimap_body_fld_lines_parse(mailstream * fd, + MMAPString * buffer, size_t * index, + uint32_t * result) +{ + return mailimap_number_parse(fd, buffer, index, result); +} + +/* + body-fld-md5 = nstring +*/ + +static int mailimap_body_fld_md5_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + body-fld-octets = number +*/ + +static int mailimap_body_fld_octets_parse(mailstream * fd, + MMAPString * buffer, size_t * index, + uint32_t * result) +{ + return mailimap_number_parse(fd, buffer, index, result); +} + +/* + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil +*/ + +/* + string SP string +*/ + +static int +mailimap_single_body_fld_param_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_single_body_fld_param ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_single_body_fld_param * param; + char * name; + char * value; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + name = NULL; + value = NULL; + + r = mailimap_string_parse(fd, buffer, &cur_token, &name, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_name; + } + + r = mailimap_string_parse(fd, buffer, &cur_token, &value, NULL, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_name; + } + + param = mailimap_single_body_fld_param_new(name, value); + if (param == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_value; + } + + * result = param; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_value: + mailimap_string_free(name); + free_name: + mailimap_string_free(value); + err: + return res; +} + +/* + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil +*/ + +static int +mailimap_body_fld_param_parse(mailstream * fd, + MMAPString * buffer, size_t * index, + struct mailimap_body_fld_param ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * param_list; + struct mailimap_body_fld_param * fld_param; + int r; + int res; + + param_list = NULL; + cur_token = * index; + + r = mailimap_nil_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + * result = NULL; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + + if (r != MAILIMAP_ERROR_PARSE) { + res = r; + goto err; + } + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, ¶m_list, + (mailimap_struct_parser *) + mailimap_single_body_fld_param_parse, + (mailimap_struct_destructor *) + mailimap_single_body_fld_param_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + fld_param = mailimap_body_fld_param_new(param_list); + if (fld_param == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = fld_param; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(param_list, + (clist_func) mailimap_single_body_fld_param_free, + NULL); + clist_free(param_list); + err: + return res; +} + +/* + body-type-1part = (body-type-basic / body-type-msg / body-type-text) + [SP body-ext-1part] +*/ + +static int +mailimap_body_type_1part_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_1part ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_body_type_1part * body_type_1part; + struct mailimap_body_type_basic * body_type_basic; + struct mailimap_body_type_msg * body_type_msg; + struct mailimap_body_type_text * body_type_text; + struct mailimap_body_ext_1part * body_ext_1part; + int type; + size_t final_token; + int r; + int res; + + cur_token = * index; + + body_type_basic = NULL; + body_type_msg = NULL; + body_type_text = NULL; + body_ext_1part = NULL; + + type = MAILIMAP_BODY_TYPE_1PART_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_body_type_msg_parse(fd, buffer, &cur_token, + &body_type_msg, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_TYPE_1PART_MSG; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_body_type_text_parse(fd, buffer, &cur_token, + &body_type_text, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_TYPE_1PART_TEXT; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_body_type_basic_parse(fd, buffer, &cur_token, + &body_type_basic, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_BODY_TYPE_1PART_BASIC; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + final_token = cur_token; + body_ext_1part = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_body_ext_1part_parse(fd, buffer, &cur_token, &body_ext_1part, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + final_token = cur_token; + else if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free; + } + } + else if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free; + } + + body_type_1part = mailimap_body_type_1part_new(type, body_type_basic, + body_type_msg, body_type_text, + body_ext_1part); + if (body_type_1part == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = final_token; + * result = body_type_1part; + + return MAILIMAP_NO_ERROR; + + free: + if (body_type_basic) + mailimap_body_type_basic_free(body_type_basic); + if (body_type_msg) + mailimap_body_type_msg_free(body_type_msg); + if (body_type_text) + mailimap_body_type_text_free(body_type_text); + if (body_ext_1part) + mailimap_body_ext_1part_free(body_ext_1part); + err: + return res; +} + +/* + body-type-basic = media-basic SP body-fields + ; MESSAGE subtype MUST NOT be "RFC822" +*/ + +static int +mailimap_body_type_basic_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_basic ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_body_type_basic * body_type_basic; + struct mailimap_media_basic * media_basic; + struct mailimap_body_fields * body_fields; + int r; + int res; + + cur_token = * index; + + media_basic = NULL; + body_fields = NULL; + + r = mailimap_media_basic_parse(fd, buffer, &cur_token, &media_basic, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_media_basic; + } + + r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_media_basic; + } + + body_type_basic = mailimap_body_type_basic_new(media_basic, body_fields); + if (body_type_basic == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_body_fields; + } + + * index = cur_token; + * result = body_type_basic; + + return MAILIMAP_NO_ERROR; + + free_body_fields: + mailimap_body_fields_free(body_fields); + free_media_basic: + mailimap_media_basic_free(media_basic); + err: + return res; +} + +/* + body-type-mpart = 1*body SP media-subtype + [SP body-ext-mpart] +*/ + +static int +mailimap_body_type_mpart_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + struct mailimap_body_type_mpart ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body_type_mpart * body_type_mpart; + clist * body_list; + size_t cur_token; + size_t final_token; + char * media_subtype; + struct mailimap_body_ext_mpart * body_ext_mpart; + int r; + int res; + + cur_token = * index; + + body_list = NULL; + media_subtype = NULL; + body_ext_mpart = NULL; + + r = mailimap_struct_multiple_parse(fd, buffer, &cur_token, + &body_list, + (mailimap_struct_parser *) + mailimap_body_parse, + (mailimap_struct_destructor *) + mailimap_body_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_body_list; + } + + r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &media_subtype, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_body_list; + } + + final_token = cur_token; + + body_ext_mpart = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_body_ext_mpart_parse(fd, buffer, &cur_token, &body_ext_mpart, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + final_token = cur_token; + else if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free_body_list; + } + } + else if (r == MAILIMAP_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free_body_list; + } + + body_type_mpart = mailimap_body_type_mpart_new(body_list, media_subtype, + body_ext_mpart); + if (body_type_mpart == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_body_ext_mpart; + } + + * result = body_type_mpart; + * index = final_token; + + return MAILIMAP_NO_ERROR; + + free_body_ext_mpart: + if (body_ext_mpart) + mailimap_body_ext_mpart_free(body_ext_mpart); + mailimap_media_subtype_free(media_subtype); + free_body_list: + clist_foreach(body_list, (clist_func) mailimap_body_free, NULL); + clist_free(body_list); + err: + return res; +} + +/* + body-type-msg = media-message SP body-fields SP envelope + SP body SP body-fld-lines +*/ + +static int +mailimap_body_type_msg_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_msg ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body_fields * body_fields; + struct mailimap_envelope * envelope; + struct mailimap_body * body; + uint32_t body_fld_lines; + struct mailimap_body_type_msg * body_type_msg; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + body_fields = NULL; + envelope = NULL; + body = NULL; + body_fld_lines = 0; + + r = mailimap_media_message_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto body_fields; + } + + r = mailimap_envelope_parse(fd, buffer, &cur_token, &envelope, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto body_fields; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto envelope; + } + + r = mailimap_body_parse(fd, buffer, &cur_token, &body, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto envelope; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto body; + } + + r = mailimap_body_fld_lines_parse(fd, buffer, &cur_token, + &body_fld_lines); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto body; + } + + body_type_msg = mailimap_body_type_msg_new(body_fields, envelope, + body, body_fld_lines); + if (body_type_msg == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto body; + } + + * result = body_type_msg; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + body: + mailimap_body_free(body); + envelope: + mailimap_envelope_free(envelope); + body_fields: + mailimap_body_fields_free(body_fields); + err: + return res; +} + +/* + body-type-text = media-text SP body-fields SP body-fld-lines +*/ + +static int +mailimap_body_type_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body_type_text ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + char * media_text; + struct mailimap_body_fields * body_fields; + uint32_t body_fld_lines; + struct mailimap_body_type_text * body_type_text; + size_t cur_token; + int r; + int res; + + media_text = NULL; + body_fields = NULL; + body_fld_lines = 0; + + cur_token = * index; + + r = mailimap_media_text_parse(fd, buffer, &cur_token, &media_text, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_media_text; + } + + r = mailimap_body_fields_parse(fd, buffer, &cur_token, &body_fields, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_media_text; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_body_fields; + } + + r = mailimap_body_fld_lines_parse(fd, buffer, &cur_token, &body_fld_lines); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_body_fields; + } + + body_type_text = mailimap_body_type_text_new(media_text, body_fields, + body_fld_lines); + if (body_type_text == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_body_fields; + } + + * result = body_type_text; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_body_fields: + mailimap_body_fields_free(body_fields); + free_media_text: + mailimap_media_text_free(media_text); + err: + return res; +} + + +/* + capability = ("AUTH=" auth-type) / atom + ; New capabilities MUST begin with "X" or be + ; registered with IANA as standard or + ; standards-track +*/ + +static int +mailimap_capability_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_capability ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + char * auth_type; + char * atom; + struct mailimap_capability * cap; + int r; + int res; + + cur_token = * index; + + auth_type = NULL; + atom = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "AUTH="); + switch (r) { + case MAILIMAP_NO_ERROR: + type = MAILIMAP_CAPABILITY_AUTH_TYPE; + + r = mailimap_auth_type_parse(fd, buffer, &cur_token, &auth_type, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + break; + + case MAILIMAP_ERROR_PARSE: + r = mailimap_atom_parse(fd, buffer, &cur_token, &atom, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_CAPABILITY_NAME; + break; + + default: + res = r; + goto err; + } + + cap = mailimap_capability_new(type, auth_type, atom); + if (cap == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = cap; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (auth_type) + mailimap_auth_type_free(auth_type); + if (atom) + mailimap_atom_free(atom); + err: + return res; +} + +/* + capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1" + *(SP capability) + ; IMAP4rev1 servers which offer RFC 1730 + ; compatibility MUST list "IMAP4" as the first + ; capability. +*/ + +/* + SP capability *(SP capability) +*/ + +static int mailimap_capability_list_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * list; + int r; + + cur_token = * index; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list, + (mailimap_struct_parser *) + mailimap_capability_parse, + (mailimap_struct_destructor *) + mailimap_capability_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + * result = list; + + return MAILIMAP_NO_ERROR; +} + +static int +mailimap_capability_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_capability_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * cap_list; +#if 0 + clist * cap_list_2; +#endif + struct mailimap_capability_data * cap_data; + int r; + int res; + + cur_token = * index; + + cap_list = NULL; +#if 0 + cap_list_2 = NULL; +#endif + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "CAPABILITY"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_capability_list_parse(fd, buffer, &cur_token, + &cap_list, + progr_rate, progr_fun); + + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + +#if 0 + if (!mailimap_space_parse(fd, buffer, &cur_token)) { + res = r; + goto free_list; + } + + if (!mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "IMAP4rev1")) + goto free_list; + + r = mailimap_capability_list_parse(fd, buffer, &cur_token, + &cap_list_2, + progr_rate, progr_fun); + + cap_list = g_list_concat(cap_list, cap_list_2); +#endif + + cap_data = mailimap_capability_data_new(cap_list); + if (cap_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + * result = cap_data; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_list: + if (cap_list) { + clist_foreach(cap_list, (clist_func) mailimap_capability_free, NULL); + clist_free(cap_list); + } + err: + return res; +} + +/* + UNIMPLEMENTED BECAUSE UNUSED (only in literal) + CHAR8 = %x01-ff + ; any OCTET except NUL, %x00 +*/ + +/* +static gboolean is_char8(gchar ch) +{ + return (ch != 0x00); +} +*/ + + +/* +UNIMPLEMENTED + command = tag SP (command-any / command-auth / command-nonauth / + command-select) CRLF + ; Modal based on state +*/ + +/* +UNIMPLEMENTED + command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command + ; Valid in all states +*/ + +/* +UNIMPLEMENTED + command-auth = append / create / delete / examine / list / lsub / + rename / select / status / subscribe / unsubscribe + ; Valid only in Authenticated or Selected state +*/ + +/* +UNIMPLEMENTED + command-nonauth = login / authenticate + ; Valid only when in Not Authenticated state +*/ + +/* +UNIMPLEMENTED + command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store / + uid / search + ; Valid only when in Selected state +*/ + +/* + continue-req = "+" SP (resp-text / base64) CRLF +*/ + +int +mailimap_continue_req_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_continue_req ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_resp_text * resp_text; + size_t cur_token; + struct mailimap_continue_req * cont_req; + char * base64; + int type; + int r; + int res; + + cur_token = * index; + + r = mailimap_plus_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + resp_text = NULL; + base64 = NULL; + + type = MAILIMAP_CONTINUE_REQ_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_base64_parse(fd, buffer, &cur_token, &base64, + progr_rate, progr_fun); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_CONTINUE_REQ_BASE64; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_text_parse(fd, buffer, &cur_token, &resp_text, + progr_rate, progr_fun); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_CONTINUE_REQ_TEXT; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_crlf_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + cont_req = mailimap_continue_req_new(type, resp_text, base64); + if (cont_req == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = cont_req; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (base64 != NULL) + mailimap_base64_free(base64); + if (resp_text != NULL) + mailimap_resp_text_free(resp_text); + err: + return res; +} + +/* + UNIMPLEMENTED + copy = "COPY" SP set SP mailbox +*/ + +/* + UNIMPLEMENTED + create = "CREATE" SP mailbox + ; Use of INBOX gives a NO error +*/ + +/* + UNIMPLEMENTED + date = date-text / DQUOTE date-text DQUOTE +*/ + +/* + UNIMPLEMENTED + date-day = 1*2DIGIT + ; Day of month +*/ + +/* +static gboolean mailimap_date_day_parse(mailstream * fd, + MMAPString * buffer, + guint32 * index, + gint * result) +{ + guint32 cur_token; + gint digit; + gint number; + + cur_token = * index; + + if (!mailimap_digit_parse(fd, buffer, &cur_token, &digit)) + return FALSE; + + number = digit; + + if (mailimap_digit_parse(fd, buffer, &cur_token, &digit)) + number = number * 10 + digit; + + * result = number; + * index = cur_token; + + return TRUE; +} +*/ + +/* + date-day-fixed = (SP DIGIT) / 2DIGIT + ; Fixed-format version of date-day +*/ + +static int mailimap_date_day_fixed_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + int * result) +{ +#ifdef UNSTRICT_SYNTAX + size_t cur_token; + uint32_t day; + int r; + + cur_token = * index; + + r = mailimap_number_parse(fd, buffer, &cur_token, &day); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + * result = day; + + return MAILIMAP_NO_ERROR; + +#else + size_t cur_token; + int r; + + cur_token = * index; + + if (mailimap_space_parse(fd, buffer, &cur_token)) { + int digit; + + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = digit; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + } + else { + int digit1; + int digit2; + + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit1); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit2); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = digit1 * 10 + digit2; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + } +#endif +} + + +/* + date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / + "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" +*/ + +static int mailimap_date_month_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result) +{ + size_t cur_token; + int month; + + cur_token = * index; + + month = mailimap_month_get_token_value(fd, buffer, &cur_token); + if (month == -1) + return MAILIMAP_ERROR_PARSE; + + * result = month; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + UNIMPLEMENTED + date-text = date-day "-" date-month "-" date-year +*/ + +/* +static struct mailimap_date_text * +mailimap_date_text_new(gint day, gint month, gint year) +{ + struct mailimap_date_text * date_text; + + date_text = g_new(struct mailimap_date_text, 1); + if (date_text == NULL) + return NULL; + + date_text->day = day; + date_text->month = month; + date_text->year = year; + + return date_text; +} + +static void mailimap_date_text_free(struct mailimap_date_text * date_text) +{ + g_free(date_text); +} + +static gboolean +mailimap_date_text_parse(mailstream * fd, MMAPString * buffer, + guint32 * index, struct mailimap_date_text ** result) +{ + struct mailimap_date_text * date_text; + gint day; + gint month; + gint year; + guint32 cur_token; + + cur_token = * index; + + if (!mailimap_date_day_parse(fd, buffer, &cur_token, &day)) + return FALSE; + + if (!mailimap_minus_parse(fd, buffer, &cur_token)) + return FALSE; + + if (!mailimap_date_month_parse(fd, buffer, &cur_token, &month)) + return FALSE; + + if (!mailimap_minus_parse(fd, buffer, &cur_token)) + return FALSE; + + if (!mailimap_date_year_parse(fd, buffer, &cur_token, &year)) + return FALSE; + + date_text = mailimap_date_text_new(day, month, year); + if (date_text == NULL) + return FALSE; + + * result = date_text; + * index = cur_token; + + return TRUE; +} +*/ + +/* + date-year = 4DIGIT +*/ + +static int mailimap_date_year_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result) +{ +#ifdef UNSTRICT_SYNTAX + uint32_t year; + int r; + size_t cur_token; + + cur_token = * index; + + r = mailimap_number_parse(fd, buffer, &cur_token, &year); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = year; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +#else + int i; + size_t cur_token; + int year; + int digit; + int r; + + cur_token = * index; + year = 0; + + for(i = 0 ; i < 4 ; i ++) { + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + year = year * 10 + digit; + } + + * result = year; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +#endif +} + +/* + date-time = DQUOTE date-day-fixed "-" date-month "-" date-year + SP time SP zone DQUOTE +*/ + +static int mailimap_date_time_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_date_time ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int day; + int month; + int year; + int hour; + int min; + int sec; + struct mailimap_date_time * date_time; + size_t cur_token; + int zone; + int r; + + cur_token = * index; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_day_fixed_parse(fd, buffer, &cur_token, &day); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_minus_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_month_parse(fd, buffer, &cur_token, &month); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_minus_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_year_parse(fd, buffer, &cur_token, &year); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_time_parse(fd, buffer, &cur_token, &hour, &min, &sec); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_zone_parse(fd, buffer, &cur_token, &zone); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + date_time = mailimap_date_time_new(day, month, year, hour, min, sec, zone); + if (date_time == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = date_time; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + UNIMPLEMENTED + delete = "DELETE" SP mailbox + ; Use of INBOX gives a NO error +*/ + +/* + digit-nz = %x31-39 + ; 1-9 +*/ + +#ifndef UNSTRICT_SYNTAX +static int is_digit_nz(char ch) +{ + return (ch >= '1') && (ch <= '9'); +} + +static int mailimap_digit_nz_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result) +{ + size_t cur_token; + + cur_token = * index; + + if (is_digit_nz(buffer->str[cur_token])) { + * result = buffer->str[cur_token] - '0'; + cur_token ++; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} +#endif + +/* + envelope = "(" env-date SP env-subject SP env-from SP env-sender SP + env-reply-to SP env-to SP env-cc SP env-bcc SP + env-in-reply-to SP env-message-id ")" +*/ + +static int mailimap_envelope_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_envelope ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * date; + char * subject; + struct mailimap_env_from * from; + struct mailimap_env_sender * sender; + struct mailimap_env_reply_to * reply_to; + struct mailimap_env_to * to; + struct mailimap_env_cc * cc; + struct mailimap_env_bcc * bcc; + char * in_reply_to; + char * message_id; + struct mailimap_envelope * envelope; + int r; + int res; + + date = NULL; + subject = NULL; + from = NULL; + sender = NULL; + reply_to = NULL; + to = NULL; + cc = NULL; + bcc = NULL; + in_reply_to = NULL; + message_id = NULL; + + cur_token = * index; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_env_date_parse(fd, buffer, &cur_token, &date, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto date; + } + + r = mailimap_env_subject_parse(fd, buffer, &cur_token, &subject, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto date; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto subject; + } + + r = mailimap_env_from_parse(fd, buffer, &cur_token, &from, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto subject; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto from; + } + + r = mailimap_env_sender_parse(fd, buffer, &cur_token, &sender, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto from; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto sender; + } + + r = mailimap_env_reply_to_parse(fd, buffer, &cur_token, &reply_to, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto sender; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto reply_to; + } + + r = mailimap_env_to_parse(fd, buffer, &cur_token, &to, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto reply_to; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto to; + } + + r = mailimap_env_cc_parse(fd, buffer, &cur_token, &cc, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto to; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto cc; + } + + r = mailimap_env_bcc_parse(fd, buffer, &cur_token, &bcc, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto cc; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto bcc; + } + + r = mailimap_env_in_reply_to_parse(fd, buffer, &cur_token, &in_reply_to, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto bcc; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto in_reply_to; + } + + r = mailimap_env_message_id_parse(fd, buffer, &cur_token, &message_id, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto in_reply_to; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto message_id; + } + + envelope = mailimap_envelope_new(date, subject, from, sender, reply_to, to, + cc, bcc, in_reply_to, message_id); + if (envelope == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto message_id; + } + + * result = envelope; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + message_id: + mailimap_env_message_id_free(message_id); + in_reply_to: + mailimap_env_in_reply_to_free(in_reply_to); + bcc: + mailimap_env_bcc_free(bcc); + cc: + mailimap_env_cc_free(cc); + to: + mailimap_env_to_free(to); + reply_to: + mailimap_env_reply_to_free(reply_to); + sender: + mailimap_env_sender_free(sender); + from: + mailimap_env_from_free(from); + subject: + mailimap_env_subject_free(date); + date: + mailimap_env_date_free(date); + err: + return res; +} + +/* + "(" 1*address ")" +*/ + +static int mailimap_address_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * address_list; + int r; + int res; + + cur_token = * index; + + address_list = NULL; + + r = mailimap_nil_parse(fd, buffer, &cur_token); + switch (r) { + case MAILIMAP_NO_ERROR: + address_list = NULL; + break; + + case MAILIMAP_ERROR_PARSE: + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_multiple_parse(fd, buffer, &cur_token, &address_list, + (mailimap_struct_parser *) + mailimap_address_parse, + (mailimap_struct_destructor *) + mailimap_address_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto address_list; + } + + break; + + default: + res = r; + goto err; + } + + * result = address_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + address_list: + if (address_list) { + clist_foreach(address_list, (clist_func) mailimap_address_free, NULL); + clist_free(address_list); + } + err: + return res; +} + +/* + env-bcc = "(" 1*address ")" / nil +*/ + +static int +mailimap_env_bcc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_bcc ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_bcc * env_bcc; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_bcc = mailimap_env_bcc_new(list); + if (env_bcc == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = env_bcc; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* + env-cc = "(" 1*address ")" / nil +*/ + +static int +mailimap_env_cc_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_cc ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_cc * env_cc; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_cc = mailimap_env_cc_new(list); + if (env_cc == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = env_cc; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* + env-date = nstring +*/ + +static int mailimap_env_date_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + env-from = "(" 1*address ")" / nil +*/ + +static int +mailimap_env_from_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_from ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_from * env_from; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_from = mailimap_env_from_new(list); + if (env_from == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = env_from; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* + env-in-reply-to = nstring +*/ + +static int mailimap_env_in_reply_to_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + env-message-id = nstring +*/ + +static int mailimap_env_message_id_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + env-reply-to = "(" 1*address ")" / nil +*/ + +static int +mailimap_env_reply_to_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_env_reply_to ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_reply_to * env_reply_to; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_reply_to = mailimap_env_reply_to_new(list); + if (env_reply_to == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = env_reply_to; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* + env-sender = "(" 1*address ")" / nil +*/ + + +static int +mailimap_env_sender_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_env_sender ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_sender * env_sender; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_sender = mailimap_env_sender_new(list); + if (env_sender == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = env_sender; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + + +/* + env-subject = nstring +*/ + +static int mailimap_env_subject_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_nstring_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + + +/* + env-to = "(" 1*address ")" / nil +*/ + +static int mailimap_env_to_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_env_to ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + size_t cur_token; + struct mailimap_env_to * env_to; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimap_address_list_parse(fd, buffer, &cur_token, &list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + env_to = mailimap_env_to_new(list); + if (env_to == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = env_to; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_address_free, NULL); + clist_free(list); + err: + return res; +} + + +/* + UNIMPLEMENTED + examine = "EXAMINE" SP mailbox +*/ + +/* + UNIMPLEMENTED + fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att / + "(" fetch-att *(SP fetch-att) ")") +*/ + +/* + UNIMPLEMENTED + fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" / + "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] / + "BODY" ["STRUCTURE"] / "UID" / + "BODY" [".PEEK"] section ["<" number "." nz-number ">"] +*/ + +/* + flag = "\Answered" / "\Flagged" / "\Deleted" / + "\Seen" / "\Draft" / flag-keyword / flag-extension + ; Does not include "\Recent" +*/ + +static int mailimap_flag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_flag * flag; + size_t cur_token; + char * flag_keyword; + char * flag_extension; + int type; + int r; + int res; + + cur_token = * index; + + flag_keyword = NULL; + flag_extension = NULL; + + type = mailimap_flag_get_token_value(fd, buffer, &cur_token); + if (type == -1) { + r = mailimap_flag_keyword_parse(fd, buffer, &cur_token, &flag_keyword, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_FLAG_KEYWORD; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_flag_extension_parse(fd, buffer, &cur_token, + &flag_extension, + progr_rate, progr_fun); + type = MAILIMAP_FLAG_EXTENSION; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + } + + flag = mailimap_flag_new(type, flag_keyword, flag_extension); + if (flag == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = flag; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (flag_keyword != NULL) + mailimap_flag_keyword_free(flag_keyword); + if (flag_extension != NULL) + mailimap_flag_extension_free(flag_extension); + err: + return res; +} + +/* + flag-extension = "\" atom + ; Future expansion. Client implementations + ; MUST accept flag-extension flags. Server + ; implementations MUST NOT generate + ; flag-extension flags except as defined by + ; future standard or standards-track + ; revisions of this specification. +*/ + +static int mailimap_flag_extension_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * atom; + int r; + + cur_token = * index; + + r = mailimap_char_parse(fd, buffer, &cur_token, '\\'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_atom_parse(fd, buffer, &cur_token, &atom, + progr_rate, progr_fun); + if (r == MAILIMAP_ERROR_PARSE) { + /* workaround for binc IMAP */ + r = mailimap_char_parse(fd, buffer, &cur_token, '*'); + if (r == MAILIMAP_NO_ERROR) { + atom = malloc(2); + if (atom == NULL) + return MAILIMAP_ERROR_MEMORY; + + atom[0] = '*'; + atom[1] = '\0'; + } + } + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = atom; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + flag-fetch = flag / "\Recent" +*/ + +static int +mailimap_flag_fetch_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag_fetch ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_flag * flag; + struct mailimap_flag_fetch * flag_fetch; + int type; + int r; + int res; + + cur_token = * index; + + flag = NULL; + + type = MAILIMAP_FLAG_FETCH_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "\\Recent"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_FLAG_FETCH_RECENT; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_flag_parse(fd, buffer, &cur_token, &flag, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_FLAG_FETCH_OTHER; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + flag_fetch = mailimap_flag_fetch_new(type, flag); + if (flag_fetch == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = flag_fetch; + + return MAILIMAP_NO_ERROR; + + free: + if (flag != NULL) + mailimap_flag_free(flag); + err: + return res; +} + +/* + flag-keyword = atom + WARNING : parse astring instead of atom to workaround RockLiffe server : + http://www.rockliffe.com/ +*/ + +static int mailimap_flag_keyword_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ +#if 0 + return mailimap_atom_parse(fd, buffer, index, result, + progr_rate, progr_fun); +#endif + return mailimap_astring_parse(fd, buffer, index, result, + progr_rate, progr_fun); +} + +/* + flag-list = "(" [flag *(SP flag)] ")" +*/ + +static int mailimap_flag_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * list; + struct mailimap_flag_list * flag_list; + int r; + int res; + + list = NULL; + cur_token = * index; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list, + (mailimap_struct_parser *) + mailimap_flag_parse, + (mailimap_struct_destructor *) + mailimap_flag_free, + progr_rate, progr_fun); + + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + flag_list = mailimap_flag_list_new(list); + if (flag_list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = flag_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimap_flag_free, NULL); + clist_free(list); + } + err: + return res; +} + +/* + flag-perm = flag / "\*" +*/ + +static int +mailimap_flag_perm_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag_perm ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_flag_perm * flag_perm; + struct mailimap_flag * flag; + int type; + int r; + int res; + + flag = NULL; + cur_token = * index; + type = MAILIMAP_FLAG_PERM_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_flag_parse(fd, buffer, &cur_token, &flag, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_FLAG_PERM_FLAG; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "\\*"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_FLAG_PERM_ALL; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + flag_perm = mailimap_flag_perm_new(type, flag); + if (flag_perm == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = flag_perm; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (flag != NULL) + mailimap_flag_free(flag); + err: + return res; +} + +/* + greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF +*/ + +int mailimap_greeting_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_greeting ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_resp_cond_auth * resp_cond_auth; + struct mailimap_resp_cond_bye * resp_cond_bye; + struct mailimap_greeting * greeting; + int type; + int r; + int res; + + cur_token = * index; + resp_cond_bye = NULL; + resp_cond_auth = NULL; + + r = mailimap_star_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_GREETING_RESP_COND_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_resp_cond_auth_parse(fd, buffer, &cur_token, &resp_cond_auth, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_GREETING_RESP_COND_AUTH; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_cond_bye_parse(fd, buffer, &cur_token, + &resp_cond_bye, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_GREETING_RESP_COND_BYE; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_crlf_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + greeting = mailimap_greeting_new(type, resp_cond_auth, resp_cond_bye); + if (greeting == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = greeting; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (resp_cond_auth) + mailimap_resp_cond_auth_free(resp_cond_auth); + if (resp_cond_bye) + mailimap_resp_cond_bye_free(resp_cond_bye); + err: + return res; +} + +/* + header-fld-name = astring +*/ + +static int +mailimap_header_fld_name_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_astring_parse(fd, buffer, index, result, + progr_rate, progr_fun); +} + +/* + header-list = "(" header-fld-name *(SP header-fld-name) ")" +*/ + +static int +mailimap_header_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_header_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_header_list * header_list; + clist * list; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list, + (mailimap_struct_parser *) + mailimap_header_fld_name_parse, + (mailimap_struct_destructor *) + mailimap_header_fld_name_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + header_list = mailimap_header_list_new(list); + if (header_list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = header_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_header_fld_name_free, NULL); + clist_free(list); + err: + return res; +} + +/* +UNIMPLEMENTED + list = "LIST" SP mailbox SP list-mailbox + +UNIMPLEMENTED + list-mailbox = 1*list-char / string + +UNIMPLEMENTED + list-char = ATOM-CHAR / list-wildcards / resp-specials +*/ + +/* + list-wildcards = "%" / "*" +*/ + +static int is_list_wildcards(char ch) +{ + switch (ch) { + case '%': + case '*': + return TRUE; + } + return FALSE; +} + + +/* + literal = "{" number "}" CRLF *CHAR8 + ; Number represents the number of CHAR8s +*/ + +static int mailimap_literal_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + uint32_t number; + MMAPString * literal; + char * literal_p; + uint32_t left; + int r; + int res; + size_t number_token; + + cur_token = * index; + + r = mailimap_oaccolade_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + number_token = cur_token; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_caccolade_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_crlf_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + literal = mmap_string_sized_new(number); + /* + literal = g_new(char, number + 1); + */ + if (literal == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + left = buffer->len - cur_token; + + if (left >= number) { + /* + if (number > 0) + strncpy(literal, buffer->str + cur_token, number); + literal[number] = 0; + */ + if (number > 0) + if (mmap_string_append_len(literal, buffer->str + cur_token, + number) == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + if ((progr_fun != NULL) && (progr_rate != 0)) + progr_fun(number, number); + + cur_token = cur_token + number; + } + else { + uint32_t needed; + uint32_t current_prog = 0; + uint32_t last_prog = 0; + + needed = number - left; + memcpy(literal->str, buffer->str + cur_token, left); + literal->len += left; + literal_p = literal->str + left; + current_prog = left; + + while (needed > 0) { + ssize_t read_bytes; + + read_bytes = mailstream_read(fd, literal_p, needed); + if (read_bytes == -1) { + res = MAILIMAP_ERROR_STREAM; + goto free_literal; + } + literal->len += read_bytes; + needed -= read_bytes; + literal_p += read_bytes; + + current_prog += read_bytes; + if ((progr_fun != NULL) && (progr_rate != 0)) + if (current_prog - last_prog > progr_rate) { + progr_fun(current_prog, number); + last_prog = current_prog; + } + } + + literal->str[number] = 0; + +#if 0 + literal->str[number] = 0; + if (mmap_string_append_len(buffer, literal->str + left, + literal->len - left) == NULL) { + res = MAILIMAP_ERROR_STREAM; + goto free_literal; + } +#endif + + if (mmap_string_truncate(buffer, number_token) == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + + if (mmap_string_append(buffer, "0}\r\n") == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + + cur_token = number_token + 4; + } + if ((progr_fun != NULL) && (progr_rate != 0)) + progr_fun(number, number); + + if (mailstream_read_line_append(fd, buffer) == NULL) { + res = MAILIMAP_ERROR_STREAM; + goto free_literal; + } + + if (mmap_string_ref(literal) < 0) { + res = MAILIMAP_ERROR_MEMORY; + goto free_literal; + } + + * result = literal->str; + if (result_len != NULL) + * result_len = literal->len; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_literal: + mmap_string_free(literal); + err: + return res; +} + +/* + UNIMPLEMENTED + login = "LOGIN" SP userid SP password + + UNIMPLEMENTED + lsub = "LSUB" SP mailbox SP list-mailbox +*/ + +/* + mailbox = "INBOX" / astring + ; INBOX is case-insensitive. All case variants of + ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX + ; not as an astring. An astring which consists of + ; the case-insensitive sequence "I" "N" "B" "O" "X" + ; is considered to be INBOX and not an astring. + ; Refer to section 5.1 for further + ; semantic details of mailbox names. +*/ + +int +mailimap_mailbox_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * name; + int r; + + cur_token = * index; + + r = mailimap_astring_parse(fd, buffer, &cur_token, &name, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = name; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / + "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" / + number SP "EXISTS" / number SP "RECENT" +*/ + +/* + "FLAGS" SP flag-list +*/ + +static int +mailimap_mailbox_data_flags_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_flag_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_flag_list * flag_list; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "FLAGS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + flag_list = NULL; + r = mailimap_flag_list_parse(fd, buffer, &cur_token, &flag_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = flag_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + "LIST" SP mailbox-list +*/ + +static int +mailimap_mailbox_data_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mailbox_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_mailbox_list * mb_list; + int r; + int res; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "LIST"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + return r; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + return r; + } + + r = mailimap_mailbox_list_parse(fd, buffer, &cur_token, &mb_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + return r; + } + + * result = mb_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "LSUB" SP mailbox-list +*/ + +static int +mailimap_mailbox_data_lsub_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mailbox_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_mailbox_list * mb_list; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "LSUB"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_list_parse(fd, buffer, &cur_token, &mb_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = mb_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "SEARCH" *(SP nz-number) +*/ + + +static int +mailimap_mailbox_data_search_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + size_t final_token; + clist * number_list; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "SEARCH"); + if (r != MAILIMAP_NO_ERROR) + return r; + + final_token = cur_token; + number_list = NULL; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &number_list, + (mailimap_struct_parser *) + mailimap_nz_number_alloc_parse, + (mailimap_struct_destructor *) + mailimap_number_alloc_free, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + final_token = cur_token; + } + + * result = number_list; + * index = final_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" +*/ + +/* + status-att SP number +*/ + +static int +mailimap_status_info_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_status_info ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int status_att; + uint32_t value; + struct mailimap_status_info * info; + int r; + + cur_token = * index; + value = 0; + + r = mailimap_status_att_parse(fd, buffer, &cur_token, &status_att); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_number_parse(fd, buffer, &cur_token, &value); + if (r != MAILIMAP_NO_ERROR) + return r; + + info = mailimap_status_info_new(status_att, value); + if (info == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = info; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" +*/ + +static int +mailimap_mailbox_data_status_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct + mailimap_mailbox_data_status ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * mb; + clist * status_info_list; + struct mailimap_mailbox_data_status * data_status; + int r; + int res; + + cur_token = * index; + mb = NULL; + status_info_list = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "STATUS"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_mailbox_parse(fd, buffer, &cur_token, &mb, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox; + } + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto mailbox; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, + &status_info_list, + (mailimap_struct_parser *) + mailimap_status_info_parse, + (mailimap_struct_destructor *) + mailimap_status_info_free, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto mailbox; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto status_info_list; + } + + data_status = mailimap_mailbox_data_status_new(mb, status_info_list); + if (data_status == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto status_info_list; + } + + * result = data_status; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + status_info_list: + if (status_info_list != NULL) { + clist_foreach(status_info_list, (clist_func) mailimap_status_info_free, + NULL); + clist_free(status_info_list); + } + mailbox: + mailimap_mailbox_free(mb); + err: + return res; +} + +/* + number SP "EXISTS" +*/ + +static int +mailimap_mailbox_data_exists_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + uint32_t * result) +{ + size_t cur_token; + uint32_t number; + int r; + + cur_token = * index; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "EXISTS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = number; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + number SP "RECENT" +*/ + +static int +mailimap_mailbox_data_recent_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + uint32_t * result) +{ + size_t cur_token; + uint32_t number; + int r; + + cur_token = * index; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "RECENT"); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = number; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / + "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" / + number SP "EXISTS" / number SP "RECENT" +*/ + +static int +mailimap_mailbox_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mailbox_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int type; + struct mailimap_flag_list * data_flags; + struct mailimap_mailbox_list * data_list; + struct mailimap_mailbox_list * data_lsub; + clist * data_search; + struct mailimap_mailbox_data_status * data_status; + uint32_t data_exists; + uint32_t data_recent; + struct mailimap_extension_data * data_extension; + + struct mailimap_mailbox_data * mailbox_data; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + data_flags = NULL; + data_list = NULL; + data_lsub = NULL; + data_search = NULL; + data_status = NULL; + data_exists = 0; + data_recent = 0; + data_extension = NULL; + + type = MAILIMAP_MAILBOX_DATA_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_mailbox_data_flags_parse(fd, buffer, &cur_token, + &data_flags, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_FLAGS; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_list_parse(fd, buffer, &cur_token, + &data_list, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_LIST; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_lsub_parse(fd, buffer, &cur_token, + &data_lsub, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_LSUB; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_search_parse(fd, buffer, &cur_token, + &data_search, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_SEARCH; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_status_parse(fd, buffer, &cur_token, + &data_status, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_STATUS; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_exists_parse(fd, buffer, &cur_token, + &data_exists); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_EXISTS; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_recent_parse(fd, buffer, &cur_token, + &data_recent); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_RECENT; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_extension_data_parse(MAILIMAP_EXTENDED_PARSER_MAILBOX_DATA, + fd, buffer, &cur_token, &data_extension, progr_rate, + progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MAILBOX_DATA_EXTENSION_DATA; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + mailbox_data = mailimap_mailbox_data_new(type, data_flags, data_list, + data_lsub, data_search, + data_status, + data_exists, data_recent, + data_extension); + + if (mailbox_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = mailbox_data; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (data_flags != NULL) + mailimap_flag_list_free(data_flags); + if (data_list != NULL) + mailimap_mailbox_list_free(data_list); + if (data_lsub != NULL) + mailimap_mailbox_list_free(data_lsub); + if (data_search != NULL) + mailimap_mailbox_data_search_free(data_search); + if (data_status != NULL) + mailimap_mailbox_data_status_free(data_status); + if (data_extension != NULL) + mailimap_extension_data_free(data_extension); + err: + return res; +} + +/* + mailbox-list = "(" [mbx-list-flags] ")" SP + (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox +*/ + +/* + DQUOTE QUOTED-CHAR DQUOTE +*/ + +static int +mailimap_mailbox_list_quoted_char_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char * result) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * index; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_quoted_char_parse(fd, buffer, &cur_token, &ch); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + * result = ch; + + return MAILIMAP_NO_ERROR; +} + +static int +mailimap_mailbox_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mailbox_list ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_mailbox_list * mb_list; + struct mailimap_mbx_list_flags * mb_flag_list; + char ch; + char * mb; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + mb_flag_list = NULL; + ch = 0; + mb = NULL; + + r = mailimap_mbx_list_flags_parse(fd, buffer, &cur_token, + &mb_flag_list, progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list_flags; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list_flags; + } + + r = mailimap_mailbox_list_quoted_char_parse(fd, buffer, &cur_token, &ch); + if (r == MAILIMAP_ERROR_PARSE) + r = mailimap_nil_parse(fd, buffer, &cur_token); + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list_flags; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list_flags; + } + + r = mailimap_mailbox_parse(fd, buffer, &cur_token, &mb, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list_flags; + } + + mb_list = mailimap_mailbox_list_new(mb_flag_list, ch, mb); + if (mb_list == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_mailbox; + } + + * result = mb_list; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_mailbox: + mailimap_mailbox_free(mb); + free_list_flags: + if (mb_flag_list != NULL) + mailimap_mbx_list_flags_free(mb_flag_list); + err: + return res; +} + +/* + mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag + *(SP mbx-list-oflag) / + mbx-list-oflag *(SP mbx-list-oflag) +*/ + +static int +mailimap_mbx_list_flags_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mbx_list_flags ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_mbx_list_flags * mbx_list_flag; + size_t cur_token; + clist * oflags; + clist * oflags_2; + int sflag; + int type; + int r; + int res; + size_t final_token; + int try_sflag; + + cur_token = * index; + final_token = cur_token; + + oflags = clist_new(); + if (oflags == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + sflag = MAILIMAP_MBX_LIST_SFLAG_ERROR; + oflags_2 = NULL; + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, + &oflags_2, + (mailimap_struct_parser *) + mailimap_mbx_list_oflag_no_sflag_parse, + (mailimap_struct_destructor *) + mailimap_mbx_list_oflag_free, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto free; + } + + try_sflag = 1; + if (r == MAILIMAP_NO_ERROR) { + clist_concat(oflags, oflags_2); + clist_free(oflags_2); + + final_token = cur_token; + try_sflag = 0; + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) + try_sflag = 1; + } + + type = MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG; + if (try_sflag) { + r = mailimap_mbx_list_sflag_parse(fd, buffer, &cur_token, &sflag); + switch (r) { + case MAILIMAP_ERROR_PARSE: + type = MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG; + break; + + case MAILIMAP_NO_ERROR: + type = MAILIMAP_MBX_LIST_FLAGS_SFLAG; + + final_token = cur_token; + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, + &oflags_2, + (mailimap_struct_parser *) mailimap_mbx_list_oflag_parse, + (mailimap_struct_destructor *) mailimap_mbx_list_oflag_free, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + if (r == MAILIMAP_NO_ERROR) { + clist_concat(oflags, oflags_2); + clist_free(oflags_2); + + final_token = cur_token; + } + } + + break; + + default: + res = r; + goto free; + } + } + + if ((clist_count(oflags) == 0) && (type == MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG)) { + res = MAILIMAP_ERROR_PARSE; + goto free; + } + + cur_token = final_token; + mbx_list_flag = mailimap_mbx_list_flags_new(type, oflags, sflag); + if (mbx_list_flag == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = mbx_list_flag; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + +free: + clist_foreach(oflags, (clist_func) mailimap_mbx_list_oflag_free, NULL); + clist_free(oflags); +err: + return res; +} + +/* + mbx-list-oflag = "\Noinferiors" / flag-extension + ; Other flags; multiple possible per LIST response +*/ + +static int +mailimap_mbx_list_oflag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mbx_list_oflag ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int type; + size_t cur_token; + struct mailimap_mbx_list_oflag * oflag; + char * flag_ext; + int r; + int res; + + cur_token = * index; + flag_ext = NULL; + type = MAILIMAP_MBX_LIST_OFLAG_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "\\Noinferiors"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_flag_extension_parse(fd, buffer, &cur_token, + &flag_ext, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + oflag = mailimap_mbx_list_oflag_new(type, flag_ext); + if (oflag == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = oflag; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (flag_ext != NULL) + mailimap_flag_extension_free(flag_ext); + err: + return res; +} + +static int +mailimap_mbx_list_oflag_no_sflag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_mbx_list_oflag ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int sflag_type; + int r; + + cur_token = * index; + + r = mailimap_mbx_list_sflag_parse(fd, buffer, &cur_token, &sflag_type); + if (r == MAILIMAP_NO_ERROR) + return MAILIMAP_ERROR_PARSE; + + return mailimap_mbx_list_oflag_parse(fd, buffer, index, result, + progr_rate, progr_fun); +} + + +/* + mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked" + ; Selectability flags; only one per LIST response +*/ + +static int +mailimap_mbx_list_sflag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + int * result) +{ + int type; + size_t cur_token; + + cur_token = * index; + + type = mailimap_mbx_list_sflag_get_token_value(fd, buffer, &cur_token); + if (type == -1) + return MAILIMAP_ERROR_PARSE; + + * result = type; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] +*/ + +/* + DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE +*/ + +static int +mailimap_media_basic_standard_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + int * result) +{ + size_t cur_token; + int type; + int r; + + cur_token = * index; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + type = mailimap_media_basic_get_token_value(fd, buffer, &cur_token); + if (type == -1) + return MAILIMAP_ERROR_PARSE; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return FALSE; + + * index = cur_token; + * result = type; + + return MAILIMAP_NO_ERROR; +} + +/* + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] +*/ + +static int +mailimap_media_basic_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_media_basic ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + char * basic_type; + char * subtype; + struct mailimap_media_basic * media_basic; + int r; + int res; + + cur_token = * index; + + basic_type = NULL; + subtype = NULL; + + type = MAILIMAP_MEDIA_BASIC_OTHER; + r = mailimap_media_basic_standard_parse(fd, buffer, &cur_token, + &type); + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_string_parse(fd, buffer, &cur_token, &basic_type, NULL, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MEDIA_BASIC_OTHER; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_basic_type; + } + + r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &subtype, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_basic_type; + } + + media_basic = mailimap_media_basic_new(type, basic_type, subtype); + if (media_basic == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_subtype; + } + + * result = media_basic; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_subtype: + mailimap_media_subtype_free(subtype); + free_basic_type: + if (basic_type != NULL) + mailimap_string_free(basic_type); + err: + return res; +} + + +/* + media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE + ; Defined in [MIME-IMT] +*/ + +static int +mailimap_media_message_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "MESSAGE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "RFC822"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + media-subtype = string + ; Defined in [MIME-IMT] +*/ + +static int +mailimap_media_subtype_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_string_parse(fd, buffer, index, result, NULL, + progr_rate, progr_fun); +} + +/* + media-text = DQUOTE "TEXT" DQUOTE SP media-subtype + ; Defined in [MIME-IMT] +*/ + +static int mailimap_media_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * media_subtype; + int r; + + cur_token = * index; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "TEXT"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_media_subtype_parse(fd, buffer, &cur_token, &media_subtype, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = media_subtype; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att)) +*/ + + +static int +mailimap_message_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_message_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + uint32_t number; + int type; + struct mailimap_msg_att * msg_att; + struct mailimap_message_data * msg_data; + int r; + int res; + + cur_token = * index; + msg_att = NULL; + + r = mailimap_nz_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_MESSAGE_DATA_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "EXPUNGE"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MESSAGE_DATA_EXPUNGE; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "FETCH"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_msg_att_parse(fd, buffer, &cur_token, &msg_att, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_MESSAGE_DATA_FETCH; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + msg_data = mailimap_message_data_new(number, type, msg_att); + if (msg_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_msg_att; + } + + * result = msg_data; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_msg_att: + if (msg_att != NULL) + mailimap_msg_att_free(msg_att); + err: + return res; +} + +/* + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" +*/ + +/* + msg-att-dynamic / msg-att-static +*/ + +static int +mailimap_msg_att_item_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_msg_att_item ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int type; + struct mailimap_msg_att_dynamic * msg_att_dynamic; + struct mailimap_msg_att_static * msg_att_static; + size_t cur_token; + struct mailimap_msg_att_item * item; + int r; + int res; + + cur_token = * index; + + msg_att_dynamic = NULL; + msg_att_static = NULL; + + type = MAILIMAP_MSG_ATT_ITEM_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_msg_att_dynamic_parse(fd, buffer, &cur_token, + &msg_att_dynamic, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_ITEM_DYNAMIC; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_static_parse(fd, buffer, &cur_token, + &msg_att_static, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_ITEM_STATIC; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + item = mailimap_msg_att_item_new(type, msg_att_dynamic, msg_att_static); + if (item == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = item; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (msg_att_dynamic != NULL) + mailimap_msg_att_dynamic_free(msg_att_dynamic); + if (msg_att_static != NULL) + mailimap_msg_att_static_free(msg_att_static); + err: + return res; +} + +/* + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" +*/ + +static int +mailimap_msg_att_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_msg_att ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * list; + struct mailimap_msg_att * msg_att; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &list, + (mailimap_struct_parser *) + mailimap_msg_att_item_parse, + (mailimap_struct_destructor *) + mailimap_msg_att_item_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + msg_att = mailimap_msg_att_new(list); + if (msg_att == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = msg_att; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimap_msg_att_item_free, NULL); + clist_free(list); + err: + return res; +} + +/* + msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")" + ; MAY change for a message +*/ + + +static int +mailimap_msg_att_dynamic_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_msg_att_dynamic ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + clist * list; + struct mailimap_msg_att_dynamic * msg_att_dyn; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "FLAGS"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, + &list, + (mailimap_struct_parser *) + mailimap_flag_fetch_parse, + (mailimap_struct_destructor *) + mailimap_flag_fetch_free, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + msg_att_dyn = mailimap_msg_att_dynamic_new(list); + if (msg_att_dyn == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = msg_att_dyn; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimap_flag_fetch_free, NULL); + clist_free(list); + } + err: + return res; +} + +/* + msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / + "RFC822" [".HEADER" / ".TEXT"] SP nstring / + "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / + "BODY" section ["<" number ">"] SP nstring / + "UID" SP uniqueid + ; MUST NOT change for a message +*/ + +/* + "ENVELOPE" SP envelope +*/ + + +static int +mailimap_msg_att_envelope_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + struct mailimap_envelope ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_envelope * env; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "ENVELOPE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_envelope_parse(fd, buffer, &cur_token, &env, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + * result = env; + + return MAILIMAP_NO_ERROR; +} + + +/* + "INTERNALDATE" SP date-time +*/ + + +static int +mailimap_msg_att_internaldate_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_date_time ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_date_time * date_time; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "INTERNALDATE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return FALSE; + + r = mailimap_date_time_parse(fd, buffer, &cur_token, &date_time, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = date_time; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "RFC822" SP nstring +*/ + +static int +mailimap_msg_att_rfc822_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * rfc822_message; + int r; + size_t length; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "RFC822"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_nstring_parse(fd, buffer, &cur_token, &rfc822_message, &length, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = rfc822_message; + if (result_len != NULL) + * result_len = length; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "RFC822" ".HEADER" SP nstring +*/ + +static int +mailimap_msg_att_rfc822_header_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * rfc822_header; + int r; + size_t length; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "RFC822"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + ".HEADER"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_nstring_parse(fd, buffer, &cur_token, &rfc822_header, &length, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = rfc822_header; + if (result_len != NULL) + * result_len = length; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "RFC822" ".TEXT" SP nstring +*/ + +static int +mailimap_msg_att_rfc822_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * rfc822_text; + int r; + size_t length; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "RFC822"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + ".TEXT"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_nstring_parse(fd, buffer, &cur_token, &rfc822_text, &length, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = rfc822_text; + if (result_len != NULL) + * result_len = length; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "RFC822.SIZE" SP number +*/ + +static int +mailimap_msg_att_rfc822_size_parse(mailstream * fd, MMAPString * buffer, + size_t * index, uint32_t * result) +{ + size_t cur_token; + uint32_t number; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "RFC822.SIZE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = number; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "BODY" SP body +*/ + + +static int +mailimap_msg_att_body_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_body ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body * body; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "BODY"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_parse(fd, buffer, &cur_token, &body, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = body; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "BODY" "STRUCTURE" SP body +*/ + + +static int +mailimap_msg_att_bodystructure_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_body ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_body * body; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "BODY"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "STRUCTURE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_body_parse(fd, buffer, &cur_token, &body, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = body; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "BODY" section ["<" number ">"] SP nstring +*/ + +static int +mailimap_msg_att_body_section_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_msg_att_body_section ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + uint32_t number; + struct mailimap_section * section; + char * body_part; + struct mailimap_msg_att_body_section * msg_att_body_section; + int r; + int res; + size_t length; + + cur_token = * index; + + section = NULL; + number = 0; + body_part = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "BODY"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_section_parse(fd, buffer, &cur_token, §ion, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_lower_parse(fd, buffer, &cur_token); + switch (r) { + case MAILIMAP_NO_ERROR: + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_section; + } + + r = mailimap_greater_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_section; + } + break; + + case MAILIMAP_ERROR_PARSE: + break; + + default: + return r; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_section; + } + + r = mailimap_nstring_parse(fd, buffer, &cur_token, &body_part, &length, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_section; + } + + msg_att_body_section = + mailimap_msg_att_body_section_new(section, number, body_part, length); + if (msg_att_body_section == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_string; + } + + * result = msg_att_body_section; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_string: + mailimap_nstring_free(body_part); + free_section: + if (section != NULL) + mailimap_section_free(section); + err: + return res; +} + +/* + "UID" SP uniqueid +*/ + +static int +mailimap_msg_att_uid_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + uint32_t * result) +{ + size_t cur_token; + uint32_t uid; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uniqueid_parse(fd, buffer, &cur_token, &uid); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + * result = uid; + + return MAILIMAP_NO_ERROR; +} + +/* + msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / + "RFC822" [".HEADER" / ".TEXT"] SP nstring / + "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / + "BODY" section ["<" number ">"] SP nstring / + "UID" SP uniqueid + ; MUST NOT change for a message +*/ + +static int +mailimap_msg_att_static_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_msg_att_static ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_envelope * env; + struct mailimap_date_time * internal_date; + char * rfc822; + char * rfc822_header; + char * rfc822_text; + uint32_t rfc822_size; + struct mailimap_body * bodystructure; + struct mailimap_body * body; + struct mailimap_msg_att_body_section * body_section; + uint32_t uid; + struct mailimap_msg_att_static * msg_att_static; + int type; + int r; + int res; + size_t length; + + cur_token = * index; + + env = NULL; + internal_date = NULL; + rfc822 = NULL; + rfc822_header = NULL; + rfc822_text = NULL; + rfc822_size = 0; + length = 0; + bodystructure = NULL; + body = NULL; + body_section = NULL; + uid = 0; + + type = MAILIMAP_MSG_ATT_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_msg_att_envelope_parse(fd, buffer, &cur_token, &env, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_ENVELOPE; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_internaldate_parse(fd, buffer, &cur_token, + &internal_date, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_INTERNALDATE; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_rfc822_parse(fd, buffer, &cur_token, + &rfc822, &length, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_RFC822; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_rfc822_header_parse(fd, buffer, &cur_token, + &rfc822_header, &length, + progr_rate, progr_fun); + type = MAILIMAP_MSG_ATT_RFC822_HEADER; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_rfc822_text_parse(fd, buffer, &cur_token, + &rfc822_text, &length, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_RFC822_TEXT; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_rfc822_size_parse(fd, buffer, &cur_token, + &rfc822_size); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_RFC822_SIZE; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_body_parse(fd, buffer, &cur_token, + &body, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_BODY; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_bodystructure_parse(fd, buffer, &cur_token, + &bodystructure, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_BODYSTRUCTURE; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_body_section_parse(fd, buffer, &cur_token, + &body_section, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_BODY_SECTION; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_msg_att_uid_parse(fd, buffer, &cur_token, + &uid); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_MSG_ATT_UID; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + msg_att_static = mailimap_msg_att_static_new(type, env, internal_date, + rfc822, rfc822_header, + rfc822_text, length, + rfc822_size, bodystructure, + body, body_section, uid); + if (msg_att_static == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = msg_att_static; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (env) + mailimap_msg_att_envelope_free(env); + if (internal_date) + mailimap_msg_att_internaldate_free(internal_date); + if (rfc822) + mailimap_msg_att_rfc822_free(rfc822); + if (rfc822_header) + mailimap_msg_att_rfc822_header_free(rfc822_header); + if (rfc822_text) + mailimap_msg_att_rfc822_text_free(rfc822_text); + if (bodystructure) + mailimap_msg_att_bodystructure_free(bodystructure); + if (body) + mailimap_msg_att_body_free(body); + if (body_section) + mailimap_msg_att_body_section_free(body_section); + err: + return res; +} + + +/* + nil = "NIL" +*/ + +static int mailimap_nil_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_token_case_insensitive_parse(fd, buffer, index, "NIL"); +} + +/* + nstring = string / nil +*/ + + +int mailimap_nstring_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + + r = mailimap_string_parse(fd, buffer, index, result, result_len, + progr_rate, progr_fun); + switch (r) { + case MAILIMAP_NO_ERROR: + return MAILIMAP_NO_ERROR; + + case MAILIMAP_ERROR_PARSE: + r = mailimap_nil_parse(fd, buffer, index); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + + * result = NULL; + if (result_len != NULL) + * result_len = 0; + return MAILIMAP_NO_ERROR; + + default: + return r; + } +} + +/* + number = 1*DIGIT + ; Unsigned 32-bit integer + ; (0 <= n < 4,294,967,296) +*/ + +static int +mailimap_number_parse(mailstream * fd, MMAPString * buffer, + size_t * index, uint32_t * result) +{ + size_t cur_token; + int digit; + uint32_t number; + int parsed; + int r; + + cur_token = * index; + parsed = FALSE; + +#ifdef UNSTRICT_SYNTAX + mailimap_space_parse(fd, buffer, &cur_token); +#endif + + number = 0; + while (1) { + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r == MAILIMAP_ERROR_PARSE) + break; + else if (r == MAILIMAP_NO_ERROR) { + number *= 10; + number += digit; + parsed = TRUE; + } + else + return r; + } + + if (!parsed) + return MAILIMAP_ERROR_PARSE; + + * result = number; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + nz-number = digit-nz *DIGIT + ; Non-zero unsigned 32-bit integer + ; (0 < n < 4,294,967,296) +*/ + +int +mailimap_nz_number_parse(mailstream * fd, MMAPString * buffer, + size_t * index, uint32_t * result) +{ +#ifdef UNSTRICT_SYNTAX + size_t cur_token; + uint32_t number; + int r; + + cur_token = * index; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (number == 0) + return MAILIMAP_ERROR_PARSE; + +#else + size_t cur_token; + int digit; + uint32_t number; + int r; + + cur_token = * index; + + r = mailimap_digit_nz_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + + number = digit; + + while (1) { + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r == MAILIMAP_ERROR_PARSE) + break; + else if (r == MAILIMAP_NO_ERROR) { + number *= 10; + number += (guint32) digit; + } + else + return r; + } +#endif + + * result = number; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + password = astring +*/ + +/* + quoted = DQUOTE *QUOTED-CHAR DQUOTE +*/ + +static int +mailimap_quoted_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + char ch; + size_t cur_token; + MMAPString * gstr_quoted; + int r; + int res; + + cur_token = * index; + +#ifdef UNSTRICT_SYNTAX + r = mailimap_space_parse(fd, buffer, &cur_token); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; +#endif + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + gstr_quoted = mmap_string_new(""); + if (gstr_quoted == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto err; + } + + while (1) { + r = mailimap_quoted_char_parse(fd, buffer, &cur_token, &ch); + if (r == MAILIMAP_ERROR_PARSE) + break; + else if (r == MAILIMAP_NO_ERROR) { + if (mmap_string_append_c(gstr_quoted, ch) == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + } + else { + res = r; + goto free; + } + } + + r = mailimap_dquote_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + if (mmap_string_ref(gstr_quoted) < 0) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = gstr_quoted->str; + + return MAILIMAP_NO_ERROR; + + free: + mmap_string_free(gstr_quoted); + err: + return res; +} + +/* + QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> / + "\" quoted-specials +*/ + +static int is_quoted_specials(char ch); + +static int +mailimap_quoted_char_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char * result) +{ + size_t cur_token; + int r; + + cur_token = * index; + + if (!is_quoted_specials(buffer->str[cur_token])) { + * result = buffer->str[cur_token]; + cur_token ++; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + else { + char quoted_special; + + r = mailimap_char_parse(fd, buffer, &cur_token, '\\'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_quoted_specials_parse(fd, buffer, &cur_token, + "ed_special); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = quoted_special; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + } +} + +/* + quoted-specials = DQUOTE / "\" +*/ + +static int is_quoted_specials(char ch) +{ + return (ch == '\"') || (ch == '\\'); +} + +static int +mailimap_quoted_specials_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char * result) +{ + size_t cur_token; + + cur_token = * index; + + if (is_quoted_specials(buffer->str[cur_token])) { + * result = buffer->str[cur_token]; + cur_token ++; + * index = cur_token; + return MAILIMAP_NO_ERROR; + } + else + return MAILIMAP_ERROR_PARSE; +} + +/* + UNIMPLEMENTED + rename = "RENAME" SP mailbox SP mailbox + ; Use of INBOX as a destination gives a NO error +*/ + +/* + response = *(continue-req / response-data) response-done +*/ + +/* + continue-req / response-data +*/ + +/* static */ int +mailimap_cont_req_or_resp_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_cont_req_or_resp_data ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data; + struct mailimap_continue_req * cont_req; + struct mailimap_response_data * resp_data; + int type; + int r; + int res; + + cur_token = * index; + + cont_req = NULL; + resp_data = NULL; + type = MAILIMAP_RESP_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_continue_req_parse(fd, buffer, &cur_token, &cont_req, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_CONT_REQ; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_response_data_parse(fd, buffer, &cur_token, &resp_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_RESP_DATA; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + /* + multi-lines response + read another response line because after that token, + there must have something (continue-req, response-data or response-done) + */ + + if (!mailstream_read_line_append(fd, buffer)) { + res = MAILIMAP_ERROR_STREAM; + goto free; + } + + cont_req_or_resp_data = + mailimap_cont_req_or_resp_data_new(type, cont_req, resp_data); + if (cont_req_or_resp_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = cont_req_or_resp_data; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (cont_req != NULL) + mailimap_continue_req_free(cont_req); + if (resp_data != NULL) + mailimap_response_data_free(resp_data); + err: + return res; +} + +/* + response = *(continue-req / response-data) response-done +*/ + +int +mailimap_response_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_response ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * cont_req_or_resp_data_list; + struct mailimap_response * resp; + struct mailimap_response_done * resp_done; + int r; + int res; + + cur_token = * index; + cont_req_or_resp_data_list = NULL; + resp_done = NULL; + + r = mailimap_struct_multiple_parse(fd, buffer, + &cur_token, &cont_req_or_resp_data_list, + (mailimap_struct_parser *) + mailimap_cont_req_or_resp_data_parse, + (mailimap_struct_destructor *) + mailimap_cont_req_or_resp_data_free, + progr_rate, progr_fun); + + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + r = mailimap_response_done_parse(fd, buffer, &cur_token, &resp_done, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_list; + } + + resp = mailimap_response_new(cont_req_or_resp_data_list, resp_done); + if (resp == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_resp_done; + } + + * result = resp; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_resp_done: + mailimap_response_done_free(resp_done); + free_list: + if (cont_req_or_resp_data_list != NULL) { + clist_foreach(cont_req_or_resp_data_list, + (clist_func) mailimap_cont_req_or_resp_data_free, NULL); + clist_free(cont_req_or_resp_data_list); + } + return res; +} + +/* + response-data = "*" SP (resp-cond-state / resp-cond-bye / + mailbox-data / message-data / capability-data) CRLF +*/ + +static int +mailimap_response_data_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_response_data * resp_data; + size_t cur_token; + int type; + struct mailimap_resp_cond_state * cond_state; + struct mailimap_resp_cond_bye * cond_bye; + struct mailimap_mailbox_data * mb_data; + struct mailimap_message_data * msg_data; + struct mailimap_capability_data * cap_data; + struct mailimap_extension_data * ext_data; + int r; + int res; + + cond_state = NULL; + cond_bye = NULL; + mb_data = NULL; + msg_data = NULL; + cap_data = NULL; + ext_data = NULL; + + cur_token = * index; + + r = mailimap_star_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMAP_RESP_DATA_TYPE_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_resp_cond_state_parse(fd, buffer, &cur_token, &cond_state, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_COND_STATE; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_cond_bye_parse(fd, buffer, &cur_token, &cond_bye, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_COND_BYE; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_mailbox_data_parse(fd, buffer, &cur_token, &mb_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_message_data_parse(fd, buffer, &cur_token, &msg_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_capability_data_parse(fd, buffer, &cur_token, &cap_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_extension_data_parse(MAILIMAP_EXTENDED_PARSER_RESPONSE_DATA, + fd, buffer, &cur_token, &ext_data, progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DATA_TYPE_EXTENSION_DATA; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_crlf_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + resp_data = mailimap_response_data_new(type, cond_state, + cond_bye, mb_data, + msg_data, cap_data, ext_data); + if (resp_data == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = resp_data; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (cond_state) + mailimap_resp_cond_state_free(cond_state); + if (cond_bye) + mailimap_resp_cond_bye_free(cond_bye); + if (mb_data) + mailimap_mailbox_data_free(mb_data); + if (msg_data) + mailimap_message_data_free(msg_data); + if (cap_data) + mailimap_capability_data_free(cap_data); + if (ext_data) + mailimap_extension_data_free(ext_data); + err: + return res; +} + +/* + response-done = response-tagged / response-fatal +*/ + +static int +mailimap_response_done_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_done ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int type; + struct mailimap_response_done * resp_done; + size_t cur_token; + struct mailimap_response_tagged * tagged; + struct mailimap_response_fatal * fatal; + int r; + int res; + + cur_token = * index; + + tagged = NULL; + fatal = NULL; + + type = MAILIMAP_RESP_DONE_TYPE_ERROR; /* removes a gcc warning */ + + r = mailimap_response_tagged_parse(fd, buffer, &cur_token, &tagged, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DONE_TYPE_TAGGED; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_response_fatal_parse(fd, buffer, &cur_token, &fatal, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_DONE_TYPE_FATAL; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + resp_done = mailimap_response_done_new(type, tagged, fatal); + if (resp_done == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = resp_done; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (tagged == NULL) + mailimap_response_tagged_free(tagged); + if (fatal == NULL) + mailimap_response_fatal_free(fatal); + err: + return res; +} + +/* + response-fatal = "*" SP resp-cond-bye CRLF + ; Server closes connection immediately +*/ + +static int +mailimap_response_fatal_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_fatal ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_resp_cond_bye * cond_bye; + struct mailimap_response_fatal * fatal; + size_t cur_token; + int res; + int r; + + cur_token = * index; + + r = mailimap_star_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_cond_bye_parse(fd, buffer, &cur_token, &cond_bye, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_crlf_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + fatal = mailimap_response_fatal_new(cond_bye); + if (fatal == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = fatal; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_resp_cond_bye_free(cond_bye); + err: + return res; +} + +/* + response-tagged = tag SP resp-cond-state CRLF +*/ + +static int +mailimap_response_tagged_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_response_tagged ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * tag; + struct mailimap_resp_cond_state * cond_state; + struct mailimap_response_tagged * resp_tagged; + int r; + int res; + + cur_token = * index; + cond_state = NULL; + + r = mailimap_tag_parse(fd, buffer, &cur_token, &tag, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_tag; + } + + r = mailimap_resp_cond_state_parse(fd, buffer, &cur_token, &cond_state, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_tag; + } + + resp_tagged = mailimap_response_tagged_new(tag, cond_state); + if (resp_tagged == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_cond_state; + } + + * result = resp_tagged; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_cond_state: + mailimap_resp_cond_state_free(cond_state); + free_tag: + mailimap_tag_free(tag); + err: + return res; +} + +/* + resp-cond-auth = ("OK" / "PREAUTH") SP resp-text + ; Authentication condition +*/ + +static int +mailimap_resp_cond_auth_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_cond_auth ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_resp_cond_auth * cond_auth; + size_t cur_token; + struct mailimap_resp_text * text; + int type; + int r; + int res; + + cur_token = * index; + text = NULL; + + type = MAILIMAP_RESP_COND_AUTH_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "OK"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_COND_AUTH_OK; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "PREAUTH"); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_COND_AUTH_PREAUTH; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_text_parse(fd, buffer, &cur_token, &text, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + cond_auth = mailimap_resp_cond_auth_new(type, text); + if (cond_auth == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = cond_auth; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_resp_text_free(text); + err: + return res; +} + +/* + resp-cond-bye = "BYE" SP resp-text +*/ + +static int +mailimap_resp_cond_bye_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_cond_bye ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_resp_cond_bye * cond_bye; + struct mailimap_resp_text * text; + int r; + int res; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, + &cur_token, "BYE"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_text_parse(fd, buffer, &cur_token, &text, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + cond_bye = mailimap_resp_cond_bye_new(text); + if (cond_bye == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = cond_bye; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_resp_text_free(text); + err: + return res; +} + +/* + resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text + ; Status condition +*/ + +static int +mailimap_resp_cond_state_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_cond_state ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_resp_cond_state * cond_state; + size_t cur_token; + struct mailimap_resp_text * text; + int type; + int r; + int res; + + cur_token = * index; + text = NULL; + + type = mailimap_resp_cond_state_get_token_value(fd, buffer, &cur_token); + if (type == -1) { + res = MAILIMAP_ERROR_PARSE; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_text_parse(fd, buffer, &cur_token, &text, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + cond_state = mailimap_resp_cond_state_new(type, text); + if (cond_state == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = cond_state; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_resp_text_free(text); + err: + return res; +} + + +/* + resp-specials = "]" +*/ + +static int is_resp_specials(char ch) +{ + switch (ch) { + case ']': + return TRUE; + }; + return FALSE; +} + +/* + resp-text = ["[" resp-text-code "]" SP] text +*/ + +/* "[" resp-text-code "]" */ + +static int +mailimap_resp_text_resp_text_code_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_text_code ** + result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_resp_text_code * text_code; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimap_obracket_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + text_code = NULL; + r = mailimap_resp_text_code_parse(fd, buffer, &cur_token, &text_code, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cbracket_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto free; + } + + * result = text_code; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_resp_text_code_free(text_code); + err: + return res; +} + +/* + resp-text = ["[" resp-text-code "]" SP] text +*/ + +static int +mailimap_resp_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_text ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_resp_text_code * text_code; + struct mailimap_resp_text * resp_text; + char * text; + int r; + int res; + + cur_token = * index; + text = NULL; + text_code = NULL; + + r = mailimap_resp_text_resp_text_code_parse(fd, buffer, &cur_token, + &text_code, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + r = mailimap_text_parse(fd, buffer, &cur_token, &text, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto free_resp_text_code; + } + + resp_text = mailimap_resp_text_new(text_code, text); + if (resp_text == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_text; + } + + * result = resp_text; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_resp_text_code: + if (text_code != NULL) + mailimap_resp_text_code_free(text_code); + free_text: + mailimap_text_free(text); + return res; +} + +/* + resp-text-code = "ALERT" / + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / + capability-data / "PARSE" / + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / + "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / + "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number / + atom [SP 1*<any TEXT-CHAR except "]">] +*/ + +/* + ALERT / PARSE / READ-ONLY / READ-WRITE / TRYCREATE +*/ + +static int +mailimap_resp_text_code_1_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + int * result) +{ + int id; + size_t cur_token; + + cur_token = * index; + + id = mailimap_resp_text_code_1_get_token_value(fd, buffer, &cur_token); + + if (id == -1) + return MAILIMAP_ERROR_PARSE; + + * result = id; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] +*/ + +/* + SP "(" astring *(SP astring) ")" +*/ + +static int +mailimap_resp_text_code_badcharset_1_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * charset; + int r; + int res; + + cur_token = * index; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &charset, + (mailimap_struct_parser *) + mailimap_astring_parse, + (mailimap_struct_destructor *) + mailimap_astring_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto charset; + } + + * index = cur_token; + * result = charset; + + return MAILIMAP_NO_ERROR; + + charset: + clist_foreach(charset, (clist_func) mailimap_string_free, NULL); + clist_free(charset); + err: + return res; +} + +/* + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] +*/ + +static int +mailimap_resp_text_code_badcharset_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * charset; + int r; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "BADCHARSET"); + if (r != MAILIMAP_NO_ERROR) + return r; + + charset = NULL; + + r = mailimap_resp_text_code_badcharset_1_parse(fd, buffer, &cur_token, + &charset, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) + return r; + + * result = charset; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" +*/ + +static int +mailimap_resp_text_code_permanentflags_parse(mailstream * fd, + MMAPString * buffer, + size_t * index, + clist ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + clist * flaglist; + int r; + int res; + + cur_token = * index; + + flaglist = NULL; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "PERMANENTFLAGS"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_oparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_struct_spaced_list_parse(fd, buffer, &cur_token, &flaglist, + (mailimap_struct_parser *) + mailimap_flag_perm_parse, + (mailimap_struct_destructor *) + mailimap_flag_perm_free, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimap_cparenth_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free; + } + + * index = cur_token; + * result = flaglist; + + return MAILIMAP_NO_ERROR; + + free: + clist_foreach(flaglist, (clist_func) mailimap_flag_perm_free, NULL); + clist_free(flaglist); + err: + return res; +} + + +/* + "UIDNEXT" SP nz-number / + "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number +*/ + +static int +mailimap_resp_text_code_number_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_text_code ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + uint32_t number; + struct mailimap_resp_text_code * resp_text_code; + int r; + + cur_token = * index; + + resp_text_code = NULL; + + type = mailimap_resp_text_code_2_get_token_value(fd, buffer, &cur_token); + if (type == -1) + return MAILIMAP_ERROR_PARSE; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_nz_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + switch (type) { + case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: + resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL, + number, 0, 0, NULL , NULL, NULL); + break; + case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: + resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL, + 0, number, 0, NULL , NULL, NULL); + break; + case MAILIMAP_RESP_TEXT_CODE_UNSEEN: + resp_text_code = mailimap_resp_text_code_new(type, NULL, NULL, NULL, + 0, 0, number, NULL , NULL, NULL); + break; + } + + if (resp_text_code == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = resp_text_code; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + atom [SP 1*<any TEXT-CHAR except "]">] +*/ + +static int is_text_char(char ch); + +/* + any TEXT-CHAR except "]" +*/ + +static int is_text_char_1(char ch) +{ + if (ch == ']') + return FALSE; + return is_text_char(ch); +} + +/* + 1*<any TEXT-CHAR except "]" +*/ + +static int +mailimap_resp_text_code_other_2_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_custom_string_parse(fd, buffer, index, result, + is_text_char_1); +} + +/* + SP 1*<any TEXT-CHAR except "]"> +*/ + +static int +mailimap_resp_text_code_other_1_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * value; + int r; + + cur_token = * index; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_resp_text_code_other_2_parse(fd, buffer, &cur_token, + &value, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = value; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + atom [SP 1*<any TEXT-CHAR except "]">] +*/ + +static int +mailimap_resp_text_code_other_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_text_code ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * atom; + char * value; + struct mailimap_resp_text_code * resp_text_code; + int r; + int res; + + cur_token = * index; + atom = NULL; + value = NULL; + + r = mailimap_atom_parse(fd, buffer, &cur_token, &atom, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_resp_text_code_other_1_parse(fd, buffer, &cur_token, + &value, progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + resp_text_code = mailimap_resp_text_code_new(MAILIMAP_RESP_TEXT_CODE_OTHER, + NULL, NULL, NULL, + 0, 0, 0, atom, value, NULL); + if (resp_text_code == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_value; + } + + * result = resp_text_code; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_value: + if (value != NULL) + free(value); + mailimap_atom_free(atom); + err: + return res; +} + + + +/* + resp-text-code = "ALERT" / + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / + capability-data / "PARSE" / + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / + "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / + "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number / + atom [SP 1*<any TEXT-CHAR except "]">] +*/ + +static int +mailimap_resp_text_code_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_resp_text_code ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + struct mailimap_resp_text_code * resp_text_code; + clist * badcharset; + clist * permanentflags; + struct mailimap_capability_data * cap_data; + struct mailimap_extension_data * ext_data; + int type; + int r; + int res; + + cur_token = * index; + + resp_text_code = NULL; + badcharset = NULL; + cap_data = NULL; + ext_data = NULL; + permanentflags = NULL; + + type = MAILIMAP_RESP_TEXT_CODE_OTHER; + r = mailimap_resp_text_code_1_parse(fd, buffer, &cur_token, &type); + if (r == MAILIMAP_NO_ERROR) { + /* do nothing */ + } + + if (r == MAILIMAP_ERROR_PARSE) { + + r = mailimap_resp_text_code_badcharset_parse(fd, buffer, &cur_token, + &badcharset, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_TEXT_CODE_BADCHARSET; + } + + if (r == MAILIMAP_ERROR_PARSE) { + + r = mailimap_capability_data_parse(fd, buffer, &cur_token, + &cap_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_text_code_permanentflags_parse(fd, buffer, &cur_token, + &permanentflags, + progr_rate, + progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_text_code_number_parse(fd, buffer, &cur_token, + &resp_text_code, + progr_rate, progr_fun); + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_extension_data_parse(MAILIMAP_EXTENDED_PARSER_RESP_TEXT_CODE, + fd, buffer, &cur_token, &ext_data, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_RESP_TEXT_CODE_EXTENSION; + } + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_resp_text_code_other_parse(fd, buffer, &cur_token, + &resp_text_code, + progr_rate, progr_fun); + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (resp_text_code == NULL) { + resp_text_code = mailimap_resp_text_code_new(type, + badcharset, cap_data, + permanentflags, + 0, 0, 0, NULL, NULL, ext_data); + if (resp_text_code == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + } + + * result = resp_text_code; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + +free: + if (permanentflags) { + clist_foreach(permanentflags, + (clist_func) mailimap_flag_perm_free, NULL); + clist_free(permanentflags); + } + if (cap_data) + mailimap_capability_data_free(cap_data); + if (badcharset) { + clist_foreach(badcharset, (clist_func) mailimap_astring_free, NULL); + clist_free(badcharset); + } + if (ext_data) + mailimap_extension_data_free(ext_data); +err: + return res; +} + +/* + UNIMPLEMENTED + search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key) + ; CHARSET argument to MUST be registered with IANA +*/ + +/* + UNIMPLEMENTED + search-key = "ALL" / "ANSWERED" / "BCC" SP astring / + "BEFORE" SP date / "BODY" SP astring / + "CC" SP astring / "DELETED" / "FLAGGED" / + "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" / + "OLD" / "ON" SP date / "RECENT" / "SEEN" / + "SINCE" SP date / "SUBJECT" SP astring / + "TEXT" SP astring / "TO" SP astring / + "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / + "UNKEYWORD" SP flag-keyword / "UNSEEN" / + ; Above this line were in [IMAP2] + "DRAFT" / "HEADER" SP header-fld-name SP astring / + "LARGER" SP number / "NOT" SP search-key / + "OR" SP search-key SP search-key / + "SENTBEFORE" SP date / "SENTON" SP date / + "SENTSINCE" SP date / "SMALLER" SP number / + "UID" SP set / "UNDRAFT" / set / + "(" search-key *(SP search-key) ")" +*/ + +/* + section = "[" [section-spec] "]" +*/ + +static int +mailimap_section_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_section_spec * section_spec; + size_t cur_token; + struct mailimap_section * section; + int r; + int res; + + cur_token = * index; + + section_spec = NULL; + + r = mailimap_obracket_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_section_spec_parse(fd, buffer, &cur_token, §ion_spec, + progr_rate, progr_fun); + if ((r != MAILIMAP_NO_ERROR) && (r != MAILIMAP_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimap_cbracket_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + if (section_spec == NULL) + section = NULL; + else { + section = mailimap_section_new(section_spec); + if (section == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + } + + * result = section; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + mailimap_section_spec_free(section_spec); + err: + return res; +} + +/* + section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / + "TEXT" + ; top-level or MESSAGE/RFC822 part +*/ + +static int +mailimap_section_msgtext_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_msgtext ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + int type; + struct mailimap_header_list * header_list; + struct mailimap_section_msgtext * msgtext; + int r; + int res; + + cur_token = * index; + + header_list = NULL; + + type = mailimap_section_msgtext_get_token_value(fd, buffer, &cur_token); + if (type == -1) { + res = MAILIMAP_ERROR_PARSE; + goto err; + } + + if (type == MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS) { + r = mailimap_header_list_parse(fd, buffer, &cur_token, &header_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + } + else if (type == MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT) { + r = mailimap_header_list_parse(fd, buffer, &cur_token, &header_list, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + } + + msgtext = mailimap_section_msgtext_new(type, header_list); + if (msgtext == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_header_list; + } + + * result = msgtext; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_header_list: + if (header_list) + mailimap_header_list_free(header_list); + err: + return res; +} + +/* + section-part = nz-number *("." nz-number) + ; body part nesting +*/ + +static int +mailimap_section_part_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_part ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_section_part * section_part; + size_t cur_token; + clist * section_id; + int r; + int res; + + cur_token = * index; + section_id = NULL; + + r = mailimap_struct_list_parse(fd, buffer, &cur_token, §ion_id, '.', + (mailimap_struct_parser *) + mailimap_nz_number_alloc_parse, + (mailimap_struct_destructor *) + mailimap_number_alloc_free, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + section_part = mailimap_section_part_new(section_id); + if (section_part == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_section_id; + } + + * result = section_part; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free_section_id: + clist_foreach(section_id, (clist_func) mailimap_number_alloc_free, NULL); + clist_free(section_id); + err: + return res; +} + +/* + section-spec = section-msgtext / (section-part ["." section-text]) +*/ + +static int +mailimap_section_spec_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_spec ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int type; + struct mailimap_section_msgtext * section_msgtext; + struct mailimap_section_part * section_part; + struct mailimap_section_text * section_text; + struct mailimap_section_spec * section_spec; + size_t cur_token; + int r; + int res; + size_t final_token; + + cur_token = * index; + + section_msgtext = NULL; + section_part = NULL; + section_text = NULL; + + r = mailimap_section_msgtext_parse(fd, buffer, &cur_token, + §ion_msgtext, + progr_rate, progr_fun); + switch (r) { + case MAILIMAP_NO_ERROR: + type = MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT; + break; + + case MAILIMAP_ERROR_PARSE: + + r = mailimap_section_part_parse(fd, buffer, &cur_token, + §ion_part, + progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + final_token = cur_token; + + type = MAILIMAP_SECTION_SPEC_SECTION_PART; + + r = mailimap_dot_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + r = mailimap_section_text_parse(fd, buffer, &cur_token, §ion_text, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) { + final_token = cur_token; + } + else if (r != MAILIMAP_ERROR_PARSE) { + res = r; + goto err; + } + } + else if (r != MAILIMAP_ERROR_PARSE) { + res = r; + goto err; + } + + cur_token = final_token; + break; + + default: + res = r; + goto err; + } + + section_spec = mailimap_section_spec_new(type, section_msgtext, + section_part, section_text); + if (section_spec == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = section_spec; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (section_msgtext) + mailimap_section_msgtext_free(section_msgtext); + if (section_part) + mailimap_section_part_free(section_part); + if (section_text) + mailimap_section_text_free(section_text); + err: + return res; +} + +/* + section-text = section-msgtext / "MIME" + ; text other than actual body part (headers, etc.) +*/ + +static int +mailimap_section_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_section_text ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + struct mailimap_section_msgtext * section_msgtext; + size_t cur_token; + struct mailimap_section_text * section_text; + int type; + int r; + int res; + + cur_token = * index; + + section_msgtext = NULL; + + type = MAILIMAP_SECTION_TEXT_ERROR; /* XXX - removes a gcc warning */ + + r = mailimap_section_msgtext_parse(fd, buffer, &cur_token, §ion_msgtext, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT; + + if (r == MAILIMAP_ERROR_PARSE) { + r= mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, "MIME"); + + if (r == MAILIMAP_NO_ERROR) + type = MAILIMAP_SECTION_TEXT_MIME; + } + + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + section_text = mailimap_section_text_new(type, section_msgtext); + if (section_text == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free; + } + + * result = section_text; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + + free: + if (section_msgtext) + mailimap_section_msgtext_free(section_msgtext); + err: + return res; +} + +/* + UNIMPLEMENTED + select = "SELECT" SP mailbox +*/ + +/* + UNIMPLEMENTED + sequence-num = nz-number / "*" + ; * is the largest number in use. For message + ; sequence numbers, it is the number of messages + ; in the mailbox. For unique identifiers, it is + ; the unique identifier of the last message in + ; the mailbox. +*/ + +/* + UNIMPLEMENTED + set = sequence-num / (sequence-num ":" sequence-num) / + (set "," set) + ; Identifies a set of messages. For message + ; sequence numbers, these are consecutive + ; numbers from 1 to the number of messages in + ; the mailbox + ; Comma delimits individual numbers, colon + ; delimits between two numbers inclusive. + ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13, + ; 14,15 for a mailbox with 15 messages. +*/ + +/* + UNIMPLEMENTED + status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")" +*/ + +/* + status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / + "UNSEEN" +*/ + +static int mailimap_status_att_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result) +{ + int type; + size_t cur_token; + + cur_token = * index; + + type = mailimap_status_att_get_token_value(fd, buffer, &cur_token); + + if (type == -1) + return MAILIMAP_ERROR_PARSE; + + * result = type; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + UNIMPLEMENTED + store = "STORE" SP set SP store-att-flags +*/ + +/* + UNIMPLEMENTED + store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP + (flag-list / (flag *(SP flag))) +*/ + +/* + string = quoted / literal +*/ + +int +mailimap_string_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * string; + int r; + size_t len; + + cur_token = * index; + + string = NULL; + len = 0; + + r = mailimap_quoted_parse(fd, buffer, &cur_token, &string, + progr_rate, progr_fun); + if (r == MAILIMAP_NO_ERROR) + len = strlen(string); + else if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_literal_parse(fd, buffer, &cur_token, &string, &len, + progr_rate, progr_fun); + } + + if (r != MAILIMAP_NO_ERROR) + return r; + + * result = string; + if (result_len != NULL) + * result_len = len; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + + +/* + UNIMPLEMENTED + subscribe = "SUBSCRIBE" SP mailbox +*/ + +/* + tag = 1*<any ASTRING-CHAR except "+"> +*/ + +/* + any ASTRING-CHAR except "+" +*/ + +static int is_tag_char(char ch) +{ + if (ch == '+') + return FALSE; + return is_astring_char(ch); +} + +/* + tag = 1*<any ASTRING-CHAR except "+"> +*/ + +static int mailimap_tag_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t cur_token; + char * tag; + int r; + + cur_token = * index; + + r = mailimap_custom_string_parse(fd, buffer, &cur_token, &tag, + is_tag_char); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + * result = tag; + + return MAILIMAP_NO_ERROR; +} + +/* + text = 1*TEXT-CHAR +*/ + +static int mailimap_text_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + return mailimap_custom_string_parse(fd, buffer, index, result, + is_text_char); +} + + +/* + TEXT-CHAR = <any CHAR except CR and LF> +*/ + +static int is_text_char(char ch) +{ + if ((ch == '\r') || (ch == '\n')) + return FALSE; + + return is_char(ch); +} + +/* + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds +*/ + +/* + 2DIGIT +*/ + +static int mailimap_2digit_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result) +{ +#ifndef UNSTRICT_SYNTAX + int digit; + int two_digit; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + + two_digit = digit; + + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + + two_digit = two_digit * 10 + digit; + + * result = two_digit; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +#else + uint32_t number; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimap_number_parse(fd, buffer, &cur_token, &number); + if (r != MAILIMAP_NO_ERROR) + return r; + + * index = cur_token; + * result = number; + + return MAILIMAP_NO_ERROR; +#endif +} + +/* + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds +*/ + +static int mailimap_time_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + int * phour, int * pmin, int * psec) +{ + size_t cur_token; + int hour; + int min; + int sec; + int r; + + cur_token = * index; + + r = mailimap_2digit_parse(fd, buffer, &cur_token, &hour); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_colon_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_2digit_parse(fd, buffer, &cur_token, &min); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_colon_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_2digit_parse(fd, buffer, &cur_token, &sec); + if (r != MAILIMAP_NO_ERROR) + return r; + + * phour = hour; + * pmin = min; + * psec = sec; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + UNIMPLEMENTED + uid = "UID" SP (copy / fetch / search / store) + ; Unique identifiers used instead of message + ; sequence numbers +*/ + +/* + uniqueid = nz-number + ; Strictly ascending +*/ + +int mailimap_uniqueid_parse(mailstream * fd, MMAPString * buffer, + size_t * index, uint32_t * result) +{ + return mailimap_nz_number_parse(fd, buffer, index, result); +} + +/* + UNIMPLEMENTED + unsubscribe = "UNSUBSCRIBE" SP mailbox +*/ + +/* + UNIMPLEMENTED + userid = astring +*/ + +/* + UNIMPLEMENTED + x-command = "X" atom <experimental command arguments> +*/ + +/* + zone = ("+" / "-") 4DIGIT + ; Signed four-digit value of hhmm representing + ; hours and minutes east of Greenwich (that is, + ; the amount that the given time differs from + ; Universal Time). Subtracting the timezone + ; from the given time will give the UT form. + ; The Universal Time zone is "+0000". +*/ + +static int mailimap_zone_parse(mailstream * fd, MMAPString * buffer, + size_t * index, int * result) +{ + size_t cur_token; + uint32_t zone; +#ifndef UNSTRICT_SYNTAX + int i; + int digit; +#endif + int sign; + int r; + + cur_token = * index; + + sign = 1; + r = mailimap_plus_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) + sign = 1; + + if (r == MAILIMAP_ERROR_PARSE) { + r = mailimap_minus_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) + sign = -1; + } + + if (r != MAILIMAP_NO_ERROR) + return r; + +#ifdef UNSTRICT_SYNTAX + r = mailimap_number_parse(fd, buffer, &cur_token, &zone); + if (r != MAILIMAP_NO_ERROR) + return r; +#else + zone = 0; + for(i = 0 ; i < 4 ; i ++) { + r = mailimap_digit_parse(fd, buffer, &cur_token, &digit); + if (r != MAILIMAP_NO_ERROR) + return r; + zone = zone * 10 + digit; + } +#endif + + zone *= sign; + + * result = zone; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_parser.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_parser.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,134 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_parser.h,v 1.10 2006/10/20 00:13:30 hoa Exp $ + */ + +#ifndef MAILIMAP_PARSER_H + +#define MAILIMAP_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +int mailimap_greeting_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_greeting ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_response_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_response ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_continue_req_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_continue_req ** result, + size_t progr_rate, + progress_function * progr_fun); + +typedef int mailimap_struct_parser(mailstream * fd, MMAPString * buffer, + size_t * index, void * result, + size_t progr_rate, + progress_function * progr_fun); +typedef void mailimap_struct_destructor(void * result); + +int +mailimap_mailbox_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_nstring_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_string_parse(mailstream * fd, MMAPString * buffer, + size_t * index, char ** result, + size_t * result_len, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_struct_spaced_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, clist ** result, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_oparenth_parse(mailstream * fd, MMAPString * buffer, + size_t * index); + +int mailimap_cparenth_parse(mailstream * fd, MMAPString * buffer, + size_t * index); + +int +mailimap_astring_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + char ** result, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_nz_number_parse(mailstream * fd, MMAPString * buffer, + size_t * index, uint32_t * result); + +int +mailimap_struct_list_parse(mailstream * fd, MMAPString * buffer, + size_t * index, clist ** result, + char symbol, + mailimap_struct_parser * parser, + mailimap_struct_destructor * destructor, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_uniqueid_parse(mailstream * fd, MMAPString * buffer, + size_t * index, uint32_t * result); + +int mailimap_colon_parse(mailstream * fd, MMAPString * buffer, + size_t * index); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_print.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_print.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1615 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_print.c,v 1.14 2004/11/21 21:53:36 hoa Exp $ + */ +#ifdef DEBUG +#include "mailimap_print.h" + +#include <stdio.h> + +static void mailimap_body_fields_print(struct mailimap_body_fields * + body_fields); +static void mailimap_envelope_print(struct mailimap_envelope * env); +static void mailimap_body_print(struct mailimap_body * body); +static void mailimap_body_fld_enc_print(struct mailimap_body_fld_enc * + fld_enc); + +static int indent_size = 0; + +static void indent() +{ + indent_size ++; +} + +static void unindent() +{ + indent_size --; +} + +static void print_indent() +{ + int i; + + for (i = 0 ; i < indent_size ; i++) + printf(" "); +} + + +static void mailimap_body_fld_lang_print(struct mailimap_body_fld_lang * + fld_lang) +{ + clistiter * cur; + + print_indent(); + printf("body-fld-lang { "); + + switch (fld_lang->lg_type) { + case MAILIMAP_BODY_FLD_LANG_SINGLE: + printf("%s ", fld_lang->lg_data.lg_single); + break; + + case MAILIMAP_BODY_FLD_LANG_LIST: + for(cur = clist_begin(fld_lang->lg_data.lg_list) ; + cur != NULL ; cur = clist_next(cur)) { + char * lang; + + lang = clist_content(cur); + + printf("%s ", lang); + } + break; + } + + print_indent(); + printf("}\n"); +} + +static void +mailimap_single_body_fld_param_print(struct mailimap_single_body_fld_param * + single) +{ + printf("(%s = %s)", single->pa_name, single->pa_value); +} + +static void mailimap_body_fld_param_print(struct mailimap_body_fld_param * + fld_param) +{ + clistiter * cur; + + print_indent(); + printf("body-fld-param { "); + + for(cur = clist_begin(fld_param->pa_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_single_body_fld_param * single; + + single = clist_content(cur); + + mailimap_single_body_fld_param_print(single); + printf(" "); + } + printf("\n"); +} + +static void mailimap_body_fld_dsp_print(struct mailimap_body_fld_dsp * fld_dsp) +{ + print_indent(); + printf("body-fld-dsp {\n"); + indent(); + + print_indent(); + printf("name { %s }\n", fld_dsp->dsp_type); + + mailimap_body_fld_param_print(fld_dsp->dsp_attributes); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_extension_list_print(clist * ext_list); + +static void mailimap_body_extension_print(struct mailimap_body_extension * ext) +{ + print_indent(); + printf("body-extention {\n"); + indent(); + + switch (ext->ext_type) { + case MAILIMAP_BODY_EXTENSION_NSTRING: + print_indent(); + printf("%s\n", ext->ext_data.ext_nstring); + break; + case MAILIMAP_BODY_EXTENSION_NUMBER: + print_indent(); + printf("%i\n", ext->ext_data.ext_number); + break; + case MAILIMAP_BODY_EXTENSION_LIST: + mailimap_body_extension_list_print(ext->ext_data.ext_body_extension_list); + break; + } + + unindent(); + print_indent(); + printf("}\n"); + +} + +static void mailimap_body_extension_list_print(clist * ext_list) +{ + clistiter * cur; + + print_indent(); + printf("body-extention-list {\n"); + indent(); + + for (cur = clist_begin(ext_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_body_extension * ext; + + ext = clist_content(cur); + + mailimap_body_extension_print(ext); + } + + unindent(); + print_indent(); + printf("}"); +} + +static void mailimap_body_ext_1part_print(struct mailimap_body_ext_1part * + body_ext_1part) +{ + print_indent(); + printf("body-type-1part {\n"); + indent(); + + print_indent(); + printf("md5 { %s }\n", body_ext_1part->bd_md5); + if (body_ext_1part->bd_disposition) { + mailimap_body_fld_dsp_print(body_ext_1part->bd_disposition); + if (body_ext_1part->bd_language) { + mailimap_body_fld_lang_print(body_ext_1part->bd_language); + + if (body_ext_1part->bd_extension_list) + mailimap_body_extension_list_print(body_ext_1part->bd_extension_list); + } + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_type_text_print(struct mailimap_body_type_text * + body_type_text) +{ + print_indent(); + printf("body-type-text {\n"); + indent(); + + print_indent(); + printf("media-text { %s }\n", body_type_text->bd_media_text); + mailimap_body_fields_print(body_type_text->bd_fields); + print_indent(); + printf("lines { %i }\n", body_type_text->bd_lines); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_type_msg_print(struct mailimap_body_type_msg * + body_type_msg) +{ + print_indent(); + printf("body-type-msg {\n"); + indent(); + + mailimap_body_fields_print(body_type_msg->bd_fields); + mailimap_envelope_print(body_type_msg->bd_envelope); + mailimap_body_print(body_type_msg->bd_body); + + print_indent(); + printf("lines { %i }\n", body_type_msg->bd_lines); + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_body_fld_enc_print(struct mailimap_body_fld_enc * fld_enc) +{ + print_indent(); + printf("body-fld-enc { "); + + switch (fld_enc->enc_type) { + case MAILIMAP_BODY_FLD_ENC_7BIT: + print_indent(); + printf("7bit"); + break; + case MAILIMAP_BODY_FLD_ENC_8BIT: + printf("8bit"); + break; + case MAILIMAP_BODY_FLD_ENC_BINARY: + printf("binary"); + break; + case MAILIMAP_BODY_FLD_ENC_BASE64: + printf("base64"); + break; + case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE: + printf("quoted-printable"); + break; + case MAILIMAP_BODY_FLD_ENC_OTHER: + printf("%s", fld_enc->enc_value); + break; + } + + printf("}\n"); +} + +static void mailimap_body_fields_print(struct mailimap_body_fields * + body_fields) +{ + print_indent(); + printf("body-fields {\n"); + indent(); + + mailimap_body_fld_param_print(body_fields->bd_parameter); + + print_indent(); + printf("body-fld-id { %s }\n", body_fields->bd_id); + printf("body-fld-desc { %s }\n", body_fields->bd_description); + mailimap_body_fld_enc_print(body_fields->bd_encoding); + printf("body-fld-octets { %i }\n", body_fields->bd_size); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_media_basic_print(struct mailimap_media_basic * + media_basic) +{ + print_indent(); + printf("media-basic {"); + + switch (media_basic->med_type) { + case MAILIMAP_MEDIA_BASIC_APPLICATION: + printf("application"); + break; + case MAILIMAP_MEDIA_BASIC_AUDIO: + printf("audio"); + break; + case MAILIMAP_MEDIA_BASIC_IMAGE: + printf("image"); + break; + case MAILIMAP_MEDIA_BASIC_MESSAGE: + printf("message"); + break; + case MAILIMAP_MEDIA_BASIC_VIDEO: + printf("video"); + break; + case MAILIMAP_MEDIA_BASIC_OTHER: + printf("%s", media_basic->med_basic_type); + break; + } + printf(" / %s }\n", media_basic->med_subtype); +} + +static void mailimap_body_type_basic_print(struct mailimap_body_type_basic * + body_type_basic) +{ + print_indent(); + printf("body-type-basic {\n"); + indent(); + + mailimap_media_basic_print(body_type_basic->bd_media_basic); + mailimap_body_fields_print(body_type_basic->bd_fields); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_body_type_1part_print(struct mailimap_body_type_1part * + body_type_1part) +{ + print_indent(); + printf("body-type-1part {\n"); + indent(); + + switch (body_type_1part->bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + mailimap_body_type_basic_print(body_type_1part->bd_data.bd_type_basic); + break; + + case MAILIMAP_BODY_TYPE_1PART_MSG: + mailimap_body_type_msg_print(body_type_1part->bd_data.bd_type_msg); + break; + + case MAILIMAP_BODY_TYPE_1PART_TEXT: + mailimap_body_type_text_print(body_type_1part->bd_data.bd_type_text); + break; + } + + if (body_type_1part->bd_ext_1part != NULL) + mailimap_body_ext_1part_print(body_type_1part->bd_ext_1part); + + unindent(); + print_indent(); + printf("\n"); +} + +static void mailimap_body_ext_mpart(struct mailimap_body_ext_mpart * ext_mpart) +{ + print_indent(); + printf("body-ext-mpart {\n"); + indent(); + + mailimap_body_fld_param_print(ext_mpart->bd_parameter); + if (ext_mpart->bd_disposition) { + mailimap_body_fld_dsp_print(ext_mpart->bd_disposition); + if (ext_mpart->bd_language) { + mailimap_body_fld_lang_print(ext_mpart->bd_language); + + if (ext_mpart->bd_extension_list) + mailimap_body_extension_list_print(ext_mpart->bd_extension_list); + } + } + + unindent(); + print_indent(); + printf("\n"); +} + +static void mailimap_body_type_mpart_print(struct mailimap_body_type_mpart * + mpart) +{ + clistiter * cur; + + print_indent(); + printf("body-type-mpart {\n"); + indent(); + + for(cur = clist_begin(mpart->bd_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_body * body; + + body = clist_content(cur); + + mailimap_body_print(body); + } + + printf("media-subtype { %s }\n", mpart->bd_media_subtype); + + if (mpart->bd_ext_mpart) + mailimap_body_ext_mpart(mpart->bd_ext_mpart); + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_body_print(struct mailimap_body * body) +{ + print_indent(); + printf("body {\n"); + indent(); + + switch (body->bd_type) { + case MAILIMAP_BODY_1PART: + mailimap_body_type_1part_print(body->bd_data.bd_body_1part); + break; + case MAILIMAP_BODY_MPART: + mailimap_body_type_mpart_print(body->bd_data.bd_body_mpart); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_date_time_print(struct mailimap_date_time * date_time) +{ + print_indent(); + printf("date-time { %i/%i/%i - %i:%i:%i %i }\n", + date_time->dt_day, date_time->dt_month, date_time->dt_year, + date_time->dt_hour, date_time->dt_min, date_time->dt_month, + date_time->dt_zone); +} + +static void mailimap_address_print(struct mailimap_address * address) +{ + print_indent(); + printf("address { name: %s, addr: %s, mailbox: %s, host: %s) }\n", + address->ad_personal_name, address->ad_source_route, + address->ad_mailbox_name, address->ad_host_name); +} + +static void mailimap_envelope_address_list_print(clist * address) +{ + clistiter * cur; + + print_indent(); + printf("envelope-address-list {\n"); + indent(); + + for(cur = clist_begin(address) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_address * addr; + + addr = clist_content(cur); + + mailimap_address_print(addr); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_envelope_print(struct mailimap_envelope * env) +{ + print_indent(); + printf("envelope {\n"); + indent(); + + print_indent(); + printf("date { %s }\n", env->env_date); + + print_indent(); + printf("subject { %s }\n", env->env_subject); + + print_indent(); + printf("from {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_from->frm_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("sender {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_sender->snd_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("reply-to {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_reply_to->rt_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("to {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_to->to_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("cc {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_cc->cc_list); + unindent(); + print_indent(); + printf("}\n"); + + print_indent(); + printf("bcc {\n"); + indent(); + mailimap_envelope_address_list_print(env->env_bcc->bcc_list); + unindent(); + print_indent(); + printf("}\n"); + + printf("in-reply-to { %s }\n", env->env_in_reply_to); + printf("message-id { %s }\n", env->env_message_id); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_header_list_print(struct mailimap_header_list * + header_list) +{ + clistiter * cur; + + print_indent(); + printf("header-list { "); + for(cur = clist_begin(header_list->hdr_list) ; cur != NULL ; + cur = clist_next(cur)) + printf("%s ", (char *) clist_content(cur)); + printf("}\n"); +} + +static void mailimap_section_msgtext_print(struct mailimap_section_msgtext * + section_msgtext) +{ + print_indent(); + printf("section-msgtext {\n"); + indent(); + + switch(section_msgtext->sec_type) { + case MAILIMAP_SECTION_MSGTEXT_HEADER: + print_indent(); + printf("header\n"); + break; + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS: + print_indent(); + printf("header fields {"); + indent(); + mailimap_header_list_print(section_msgtext->sec_header_list); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT: + print_indent(); + printf("header fields not {"); + indent(); + mailimap_header_list_print(section_msgtext->sec_header_list); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_SECTION_MSGTEXT_TEXT: + print_indent(); + printf("text\n"); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_section_part_print(struct mailimap_section_part * + section_part) +{ + clistiter * cur; + + print_indent(); + printf("section-part { "); + + for(cur = clist_begin(section_part->sec_id) ; + cur != NULL ; cur = clist_next(cur)) { + printf("%i", * ((uint32_t *) clist_content(cur))); + if (clist_next(cur) != NULL) + printf("."); + } + printf(" }\n"); +} + +static void mailimap_section_text_print(struct mailimap_section_text * + section_text) +{ + print_indent(); + printf("section-text {\n"); + indent(); + + switch (section_text->sec_type) { + case MAILIMAP_SECTION_TEXT_MIME: + print_indent(); + printf("MIME"); + break; + case MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT: + mailimap_section_msgtext_print(section_text->sec_msgtext); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_section_spec_print(struct mailimap_section_spec * + section_spec) +{ + print_indent(); + printf("section-spec {"); + indent(); + + switch(section_spec->sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + mailimap_section_msgtext_print(section_spec->sec_data.sec_msgtext); + break; + case MAILIMAP_SECTION_SPEC_SECTION_PART: + mailimap_section_part_print(section_spec->sec_data.sec_part); + if (section_spec->sec_text != NULL) + mailimap_section_text_print(section_spec->sec_text); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_section_print(struct mailimap_section * section) +{ + print_indent(); + printf("section {\n"); + indent(); + + if (section != NULL) + if (section->sec_spec != NULL) + mailimap_section_spec_print(section->sec_spec); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_body_section_print(struct + mailimap_msg_att_body_section * + msg_att_body_section) +{ + print_indent(); + printf("msg-att-body-section {\n"); + indent(); + + mailimap_section_print(msg_att_body_section->sec_section); + printf("origin-octet: %i\n", msg_att_body_section->sec_origin_octet); + printf("body-part: %s\n", msg_att_body_section->sec_body_part); + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_msg_att_static_print(struct mailimap_msg_att_static * + msg_att_static) +{ + print_indent(); + printf("msg-att-static {\n"); + indent(); + + switch (msg_att_static->att_type) { + + case MAILIMAP_MSG_ATT_ENVELOPE: + print_indent(); + printf("envelope {\n"); + indent(); + print_indent(); + mailimap_envelope_print(msg_att_static->att_data.att_env); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_INTERNALDATE: + print_indent(); + printf("internaldate {\n"); + indent(); + print_indent(); + mailimap_date_time_print(msg_att_static->att_data.att_internal_date); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822: + print_indent(); + printf("rfc822 {\n"); + printf("%s\n", msg_att_static->att_data.att_rfc822.att_content); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822_HEADER: + print_indent(); + printf("rfc822-header {\n"); + printf("%s\n", msg_att_static->att_data.att_rfc822_header.att_content); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822_TEXT: + print_indent(); + printf("rfc822-text {\n"); + printf("%s\n", msg_att_static->att_data.att_rfc822_text.att_content); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_RFC822_SIZE: + print_indent(); + printf("rfc822-size { %i }\n", msg_att_static->att_data.att_rfc822_size); + break; + + case MAILIMAP_MSG_ATT_BODY: + print_indent(); + printf("body {\n"); + indent(); + print_indent(); + mailimap_body_print(msg_att_static->att_data.att_body); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + print_indent(); + printf("bodystructure {\n"); + indent(); + print_indent(); + mailimap_body_print(msg_att_static->att_data.att_bodystructure); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_BODY_SECTION: + print_indent(); + printf("body-section {\n"); + indent(); + print_indent(); + mailimap_msg_att_body_section_print(msg_att_static->att_data.att_body_section); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MSG_ATT_UID: + printf("uid { %i }\n", msg_att_static->att_data.att_uid); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_flag_print(struct mailimap_flag * flag); + +static void mailimap_flag_fetch_print(struct mailimap_flag_fetch * flag) +{ + print_indent(); + printf("flag fetch {\n"); + indent(); + + switch (flag->fl_type) { + case MAILIMAP_FLAG_FETCH_RECENT: + printf("recent\n"); + break; + case MAILIMAP_FLAG_FETCH_OTHER: + print_indent(); + printf("flag {\n"); + indent(); + mailimap_flag_print(flag->fl_flag); + unindent(); + print_indent(); + printf("}\n"); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_dynamic_print(struct mailimap_msg_att_dynamic * + dynamic) +{ + clistiter * cur; + + print_indent(); + printf("msg-att-dynamic {\n"); + indent(); + + for(cur = clist_begin(dynamic->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_flag_fetch * flag; + + flag = (struct mailimap_flag_fetch *) clist_content(cur); + mailimap_flag_fetch_print(flag); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_item_print(struct mailimap_msg_att_item * item) +{ + print_indent(); + printf("msg-att-item {\n"); + indent(); + + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ITEM_DYNAMIC: + mailimap_msg_att_dynamic_print(item->att_data.att_dyn); + break; + case MAILIMAP_MSG_ATT_ITEM_STATIC: + mailimap_msg_att_static_print(item->att_data.att_static); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_msg_att_print(struct mailimap_msg_att * msg_att) +{ + clistiter * cur; + + print_indent(); + printf("msg-att {\n"); + indent(); + + for(cur = clist_begin(msg_att->att_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_msg_att_item * item; + + item = clist_content(cur); + + mailimap_msg_att_item_print(item); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_message_data_print(struct mailimap_message_data * + msg_data) +{ + print_indent(); + printf("message-data {\n"); + indent(); + + switch (msg_data->mdt_type) { + case MAILIMAP_MESSAGE_DATA_EXPUNGE: + print_indent(); + printf("expunged { %i }\n", msg_data->mdt_number); + break; + case MAILIMAP_MESSAGE_DATA_FETCH: + print_indent(); + printf("message-number { %i }\n", msg_data->mdt_number); + mailimap_msg_att_print(msg_data->mdt_msg_att); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_status_att_print(int status_att) +{ + print_indent(); + printf("status-att { "); + + switch(status_att) { + case MAILIMAP_STATUS_ATT_MESSAGES: + printf("messages"); + break; + case MAILIMAP_STATUS_ATT_RECENT: + printf("recent"); + break; + case MAILIMAP_STATUS_ATT_UIDNEXT: + printf("uidnext"); + break; + case MAILIMAP_STATUS_ATT_UIDVALIDITY: + printf("status att uidvalidity"); + break; + case MAILIMAP_STATUS_ATT_UNSEEN: + printf("status att unseen"); + break; + } + + printf(" \n"); +} + +static void +mailimap_status_info_print(struct mailimap_status_info * info) +{ + print_indent(); + printf("status-info {\n"); + indent(); + + mailimap_status_att_print(info->st_att); + + print_indent(); + printf("value { %i }\n", info->st_value); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void +mailimap_mailbox_data_status_print(struct mailimap_mailbox_data_status * + mb_data_status) +{ + clistiter * cur; + + print_indent(); + printf("mailbox-data-status {\n"); + indent(); + + print_indent(); + printf("mailbox { %s }\n", mb_data_status->st_mailbox); + + for(cur = clist_begin(mb_data_status->st_info_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_status_info * info; + + info = clist_content(cur); + + mailimap_status_info_print(info); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_mbx_list_oflag_print(struct mailimap_mbx_list_oflag * + oflag) +{ + print_indent(); + printf("mbx-list-oflag { "); + + switch (oflag->of_type) { + case MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS: + printf("noinferiors"); + break; + case MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT: + printf("%s", oflag->of_flag_ext); + break; + } + + printf(" }\n"); +} + +static void mailimap_mbx_list_sflag_print(int sflag) +{ + print_indent(); + printf("mbx-list-sflag { "); + + switch (sflag) { + case MAILIMAP_MBX_LIST_SFLAG_MARKED: + printf("marked"); + break; + case MAILIMAP_MBX_LIST_SFLAG_NOSELECT: + printf("noselected"); + break; + case MAILIMAP_MBX_LIST_SFLAG_UNMARKED: + printf("unmarked"); + break; + } + + printf(" }\n"); +} + +static void mailimap_mbx_list_flags_print(struct mailimap_mbx_list_flags * + mbx_list_flags) +{ + clistiter * cur; + + print_indent(); + printf("mbx-list-flags {"); + indent(); + + if (mbx_list_flags->mbf_type == MAILIMAP_MBX_LIST_FLAGS_SFLAG) + mailimap_mbx_list_sflag_print(mbx_list_flags->mbf_sflag); + + for(cur = clist_begin(mbx_list_flags->mbf_oflags) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_mbx_list_oflag * oflag; + + oflag = clist_content(cur); + + mailimap_mbx_list_oflag_print(oflag); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_mailbox_list_print(struct mailimap_mailbox_list * mb_list) +{ + print_indent(); + printf("mailbox-list {\n"); + indent(); + + mailimap_mbx_list_flags_print(mb_list->mb_flag); + printf("dir-separator { %c }\n", mb_list->mb_delimiter); + printf("mailbox { %s }\n", mb_list->mb_name); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_flag_list_print(struct mailimap_flag_list * flag_list) +{ + clistiter * cur; + + print_indent(); + printf("flag-list {\n"); + indent(); + + for(cur = clist_begin(flag_list->fl_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_flag * flag; + + flag = clist_content(cur); + + print_indent(); + mailimap_flag_print(flag); + printf("\n"); + } + + unindent(); + print_indent(); + printf("}\n"); +} + + +static void mailimap_mailbox_data_print(struct mailimap_mailbox_data * mb_data) +{ + clistiter * cur; + + print_indent(); + printf("mailbox-data {\n"); + indent(); + + switch (mb_data->mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + print_indent(); + printf("flags {\n"); + indent(); + mailimap_flag_list_print(mb_data->mbd_data.mbd_flags); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_LIST: + print_indent(); + printf("list {\n"); + indent(); + mailimap_mailbox_list_print(mb_data->mbd_data.mbd_list); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_LSUB: + print_indent(); + printf("lsub {\n"); + indent(); + mailimap_mailbox_list_print(mb_data->mbd_data.mbd_lsub); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_SEARCH: + print_indent(); + printf("search { "); + for(cur = clist_begin(mb_data->mbd_data.mbd_search) ; + cur != NULL ; cur = clist_next(cur)) { + uint32_t * id; + + id = clist_content(cur); + printf("%i ", * id); + } + printf(" }\n"); + break; + + case MAILIMAP_MAILBOX_DATA_STATUS: + print_indent(); + printf("status {\n"); + indent(); + mailimap_mailbox_data_status_print(mb_data->mbd_data.mbd_status); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_MAILBOX_DATA_EXISTS: + print_indent(); + printf("exists { %i }\n", mb_data->mbd_data.mbd_exists); + break; + + case MAILIMAP_MAILBOX_DATA_RECENT: + print_indent(); + printf("recent { %i }\n", mb_data->mbd_data.mbd_recent); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void +mailimap_resp_text_code_print(struct mailimap_resp_text_code * text_code); + +static void mailimap_resp_text_print(struct mailimap_resp_text * resp_text); + +static void mailimap_resp_cond_bye_print(struct mailimap_resp_cond_bye * + resp_cond_bye) +{ + print_indent(); + printf("resp-cond-bye {\n"); + indent(); + mailimap_resp_text_print(resp_cond_bye->rsp_text); + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_resp_cond_state_print(struct mailimap_resp_cond_state * + resp_cond_state) +{ + print_indent(); + printf("resp-cond-state {\n"); + indent(); + + switch(resp_cond_state->rsp_type) { + case MAILIMAP_RESP_COND_STATE_OK: + print_indent(); + printf("OK\n"); + break; + case MAILIMAP_RESP_COND_STATE_NO: + print_indent(); + printf("NO\n"); + break; + case MAILIMAP_RESP_COND_STATE_BAD: + print_indent(); + printf("BAD\n"); + break; + } + + mailimap_resp_text_print(resp_cond_state->rsp_text); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_capability_data_print(struct mailimap_capability_data * + cap_data); + +static void mailimap_response_data_print(struct mailimap_response_data * + resp_data) +{ + print_indent(); + printf("response-data {\n"); + indent(); + + switch (resp_data->rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + mailimap_resp_cond_state_print(resp_data->rsp_data.rsp_cond_state); + break; + case MAILIMAP_RESP_DATA_TYPE_COND_BYE: + mailimap_resp_cond_bye_print(resp_data->rsp_data.rsp_bye); + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + mailimap_mailbox_data_print(resp_data->rsp_data.rsp_mailbox_data); + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + mailimap_message_data_print(resp_data->rsp_data.rsp_message_data); + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + mailimap_capability_data_print(resp_data->rsp_data.rsp_capability_data); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_flag_print(struct mailimap_flag * flag) +{ + printf("flag { "); + + switch (flag->fl_type) { + case MAILIMAP_FLAG_ANSWERED: + printf("answered"); + break; + + case MAILIMAP_FLAG_FLAGGED: + printf("flagged"); + break; + + case MAILIMAP_FLAG_DELETED: + printf("deleted"); + break; + + case MAILIMAP_FLAG_SEEN: + printf("seen"); + break; + + case MAILIMAP_FLAG_DRAFT: + printf("flag draft"); + break; + + case MAILIMAP_FLAG_KEYWORD: + printf("keyword { %s }", flag->fl_data.fl_keyword); + break; + + case MAILIMAP_FLAG_EXTENSION: + printf("extention { %s }", flag->fl_data.fl_extension); + break; + } + + printf(" }"); +} + +static void mailimap_flag_perm_print(struct mailimap_flag_perm * flag_perm) +{ + print_indent(); + printf("flag-perm { "); + + switch (flag_perm->fl_type) { + case MAILIMAP_FLAG_PERM_FLAG: + mailimap_flag_print(flag_perm->fl_flag); + break; + + case MAILIMAP_FLAG_PERM_ALL: + printf("all"); + break; + } + + printf(" }\n"); +} + +static void mailimap_capability_print(struct mailimap_capability * cap) +{ + print_indent(); + printf("capability { "); + + switch (cap->cap_type) { + case MAILIMAP_CAPABILITY_AUTH_TYPE: + printf("auth { %s }", cap->cap_data.cap_auth_type); + break; + case MAILIMAP_CAPABILITY_NAME: + printf("atom { %s }", cap->cap_data.cap_name); + break; + } + + printf(" }\n"); +} + +static void mailimap_capability_data_print(struct mailimap_capability_data * + cap_data) +{ + clistiter * cur; + + print_indent(); + printf("capability-data {\n"); + indent(); + + for(cur = clist_begin(cap_data->cap_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_capability * cap; + + cap = clist_content(cur); + + mailimap_capability_print(cap); + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void +mailimap_resp_text_code_print(struct mailimap_resp_text_code * text_code) +{ + clistiter * cur; + + print_indent(); + printf("resp-text-code {\n"); + indent(); + + switch (text_code->rc_type) { + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + print_indent(); + printf("badcharset { "); + for(cur = clist_begin(text_code->rc_data.rc_badcharset) ; cur != NULL ; + cur = clist_next(cur)) + printf("%s ", (char *) clist_content(cur)); + printf("}\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + print_indent(); + printf("capability {\n"); + indent(); + mailimap_capability_data_print(text_code->rc_data.rc_cap_data); + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + print_indent(); + printf("permanent-flags {\n"); + indent(); + cur = clist_begin(text_code->rc_data.rc_perm_flags); + while (cur != NULL) { + mailimap_flag_perm_print(clist_content(cur)); + cur = clist_next(cur); + } + unindent(); + print_indent(); + printf("}\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_ONLY: + print_indent(); + printf("readonly\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_READ_WRITE: + print_indent(); + printf("readwrite\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_TRY_CREATE: + print_indent(); + printf("trycreate\n"); + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: + print_indent(); + printf("uidnext { %i }\n", text_code->rc_data.rc_uidnext); + break; + + case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: + print_indent(); + printf("uidvalidity { %i }\n", text_code->rc_data.rc_uidvalidity); + break; + + case MAILIMAP_RESP_TEXT_CODE_UNSEEN: + print_indent(); + printf("unseen { %i }\n", text_code->rc_data.rc_first_unseen); + break; + + case MAILIMAP_RESP_TEXT_CODE_OTHER: + print_indent(); + printf("other { %s = %s }\n", + text_code->rc_data.rc_atom.atom_name, + text_code->rc_data.rc_atom.atom_value); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_resp_text_print(struct mailimap_resp_text * resp_text) +{ + print_indent(); + printf("resp-text {\n"); + indent(); + + if (resp_text->rsp_code) + mailimap_resp_text_code_print(resp_text->rsp_code); + print_indent(); + printf("text { %s }\n", resp_text->rsp_text); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_continue_req_print(struct mailimap_continue_req * + cont_req) +{ + print_indent(); + printf("continue-req {\n"); + indent(); + + switch (cont_req->cr_type) { + case MAILIMAP_CONTINUE_REQ_TEXT: + print_indent(); + printf("resp-text {\n"); + indent(); + mailimap_resp_text_print(cont_req->cr_data.cr_text); + unindent(); + print_indent(); + printf("}\n"); + break; + case MAILIMAP_CONTINUE_REQ_BASE64: + printf("base64 { %s }\n", cont_req->cr_data.cr_base64); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_cont_req_or_resp_data_print(struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data) +{ + print_indent(); + printf("cont-req-or-resp-data {\n"); + indent(); + + switch (cont_req_or_resp_data->rsp_type) { + case MAILIMAP_RESP_CONT_REQ: + mailimap_continue_req_print(cont_req_or_resp_data->rsp_data.rsp_cont_req); + break; + case MAILIMAP_RESP_RESP_DATA: + mailimap_response_data_print(cont_req_or_resp_data->rsp_data.rsp_resp_data); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_response_tagged_print(struct mailimap_response_tagged * + tagged) +{ + print_indent(); + printf("response-tagged {\n"); + indent(); + + print_indent(); + printf("tag { %s }\n", tagged->rsp_tag); + mailimap_resp_cond_state_print(tagged->rsp_cond_state); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_response_fatal_print(struct mailimap_response_fatal * + fatal) +{ + print_indent(); + printf("response-fatal {\n"); + indent(); + + mailimap_resp_cond_bye_print(fatal->rsp_bye); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_response_done_print(struct mailimap_response_done * + resp_done) +{ + print_indent(); + printf("response-done {\n"); + indent(); + + switch (resp_done->rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + mailimap_response_tagged_print(resp_done->rsp_data.rsp_tagged); + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + mailimap_response_fatal_print(resp_done->rsp_data.rsp_fatal); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} + +void mailimap_response_print(struct mailimap_response * resp) +{ + clistiter * cur; + + print_indent(); + printf("response {\n"); + indent(); + + for(cur = clist_begin(resp->rsp_cont_req_or_resp_data_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimap_cont_req_or_resp_data * resp; + + resp = clist_content(cur); + + mailimap_cont_req_or_resp_data_print(resp); + } + + mailimap_response_done_print(resp->rsp_resp_done); + + unindent(); + print_indent(); + printf("}\n"); +} + +static void mailimap_resp_cond_auth_print(struct mailimap_resp_cond_auth * + cond_auth) +{ + print_indent(); + printf("resp-cond-auth {\n"); + indent(); + + switch (cond_auth->rsp_type) { + case MAILIMAP_RESP_COND_AUTH_OK: + print_indent(); + printf("OK\n"); + case MAILIMAP_RESP_COND_AUTH_PREAUTH: + print_indent(); + printf("PREAUTH\n"); + } + mailimap_resp_text_print(cond_auth->rsp_text); + + unindent(); + print_indent(); + printf("}\n"); +} + +void mailimap_greeting_print(struct mailimap_greeting * greeting) +{ + print_indent(); + printf("greeting {\n"); + indent(); + + switch(greeting->gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + mailimap_resp_cond_auth_print(greeting->gr_data.gr_auth); + break; + case MAILIMAP_GREETING_RESP_COND_BYE: + mailimap_resp_cond_bye_print(greeting->gr_data.gr_bye); + break; + } + + unindent(); + print_indent(); + printf("}\n"); +} +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_print.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_print.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,54 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_print.h,v 1.6 2004/11/21 21:53:36 hoa Exp $ + */ + +#ifndef MAILIMAP_PRINT_H + +#define MAILIMAP_PRINT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +void mailimap_response_print(struct mailimap_response * resp); + +void mailimap_greeting_print(struct mailimap_greeting * greeting); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_sender.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_sender.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,2738 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_sender.c,v 1.29 2006/10/20 00:13:30 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailstream.h" +#include "mailimap_keywords.h" +#include "mailimap_sender.h" +#include "clist.h" +#include "mail.h" +#include <string.h> + +#include <stdio.h> +#include <ctype.h> + +/* + TODO : + implement progression for literal +*/ + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + +static int mailimap_atom_send(mailstream * fd, const char * atom); + +static int mailimap_auth_type_send(mailstream * fd, const char * auth_type); + +static int mailimap_base64_send(mailstream * fd, const char * base64); + + +static int mailimap_date_send(mailstream * fd, + struct mailimap_date * date); + +static int mailimap_date_day_send(mailstream * fd, int day); + +static int mailimap_date_month_send(mailstream * fd, int month); + + +/* +static gboolean mailimap_date_text_send(mailstream * fd, + struct mailimap_date_text * date_text); +*/ + + +static int mailimap_date_year_send(mailstream *fd, int year); + +static int +mailimap_date_time_send(mailstream * fd, + struct mailimap_date_time * date_time); + +static int mailimap_digit_send(mailstream * fd, int digit); + + + +static int +mailimap_fetch_type_send(mailstream * fd, + struct mailimap_fetch_type * fetch_type); + + +static int mailimap_fetch_att_send(mailstream * fd, + struct mailimap_fetch_att * fetch_att); + + +static int mailimap_flag_send(mailstream * fd, + struct mailimap_flag * flag); + + +static int mailimap_flag_extension_send(mailstream * fd, + const char * flag_extension); + + +static int mailimap_flag_keyword_send(mailstream * fd, + const char * flag_keyword); + + +static int mailimap_flag_list_send(mailstream * fd, + struct mailimap_flag_list * flag_list); + + + +static int mailimap_header_fld_name_send(mailstream * fd, const char * header); + + +static int +mailimap_header_list_send(mailstream * fd, + struct mailimap_header_list * header_list); + +static int mailimap_number_send(mailstream * fd, uint32_t number); + +static int mailimap_password_send(mailstream * fd, const char * pass); + +static int mailimap_quoted_char_send(mailstream * fd, char ch); + + +static int mailimap_search_key_send(mailstream * fd, + struct mailimap_search_key * key); + +static int +mailimap_section_send(mailstream * fd, + struct mailimap_section * section); + +static int +mailimap_section_msgtext_send(mailstream * fd, + struct mailimap_section_msgtext * + section_msgtext); + + +static int +mailimap_section_part_send(mailstream * fd, + struct mailimap_section_part * section); + + +static int +mailimap_section_spec_send(mailstream * fd, + struct mailimap_section_spec * section_spec); + + +static int +mailimap_section_text_send(mailstream * fd, + struct mailimap_section_text * section_text); + + +static int +mailimap_sequence_num_send(mailstream * fd, uint32_t sequence_num); + + +static int mailimap_set_item_send(mailstream * fd, + struct mailimap_set_item * item); + + +static int mailimap_status_att_send(mailstream * fd, int * status_att); + + + +static int +mailimap_store_att_flags_send(mailstream * fd, + struct mailimap_store_att_flags * store_flags); + + +static int mailimap_userid_send(mailstream * fd, const char * user); + + + + + + + + + + + + + + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + + +static inline int mailimap_sized_token_send(mailstream * fd, const char * atom, + size_t len) +{ + if (mailstream_send_data_crlf(fd, atom, len, 0, NULL) == -1) + return MAILIMAP_ERROR_STREAM; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_token_send(mailstream * fd, const char * atom) +{ + return mailimap_sized_token_send(fd, atom, strlen(atom)); +} + +int mailimap_char_send(mailstream * fd, char ch) +{ + if (mailstream_write(fd, &ch, 1) == -1) + return MAILIMAP_ERROR_STREAM; + + return MAILIMAP_NO_ERROR; +} + +static int +mailimap_struct_list_send(mailstream * fd, clist * list, + char symbol, + mailimap_struct_sender * sender) +{ + clistiter * cur; + void * elt; + int r; + + cur = clist_begin(list); + + if (cur == NULL) + return MAILIMAP_NO_ERROR; + + elt = clist_content(cur); + r = (* sender)(fd, elt); + if (r != MAILIMAP_NO_ERROR) + return r; + cur = clist_next(cur); + + while (cur != NULL) { + r = mailimap_char_send(fd, symbol); + if (r != MAILIMAP_NO_ERROR) + return r; + elt = clist_content(cur); + r = (* sender)(fd, elt); + if (r != MAILIMAP_NO_ERROR) + return r; + cur = clist_next(cur); + } + + return MAILIMAP_NO_ERROR; +} + + +int +mailimap_struct_spaced_list_send(mailstream * fd, clist * list, + mailimap_struct_sender * sender) +{ + return mailimap_struct_list_send(fd, list, ' ', sender); +} + +int mailimap_space_send(mailstream * fd) +{ + return mailimap_char_send(fd, ' '); +} + +int mailimap_crlf_send(mailstream * fd) +{ + int r; + + r = mailimap_char_send(fd, '\r'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '\n'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_oparenth_send(mailstream * fd) +{ + return mailimap_char_send(fd, '('); +} + +static int mailimap_cparenth_send(mailstream * fd) +{ + return mailimap_char_send(fd, ')'); +} + +static int mailimap_dquote_send(mailstream * fd) +{ + return mailimap_char_send(fd, '"'); +} + +/* + address = "(" addr-name SP addr-adl SP addr-mailbox SP + addr-host ")" + + addr-adl = nstring + ; Holds route from [RFC-822] route-addr if + ; non-NIL + + addr-host = nstring + ; NIL indicates [RFC-822] group syntax. + ; Otherwise, holds [RFC-822] domain name + + addr-mailbox = nstring + ; NIL indicates end of [RFC-822] group; if + ; non-NIL and addr-host is NIL, holds + ; [RFC-822] group name. + ; Otherwise, holds [RFC-822] local-part + ; after removing [RFC-822] quoting + + addr-name = nstring + ; If non-NIL, holds phrase from [RFC-822] + ; mailbox after removing [RFC-822] quoting +*/ + +/* +=> append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP + literal +*/ + +int mailimap_append_send(mailstream * fd, + const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + size_t literal_size) +{ + int r; + + r = mailimap_token_send(fd, "APPEND"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mailbox); + if (r != MAILIMAP_NO_ERROR) + return r; + if (flag_list != NULL) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_flag_list_send(fd, flag_list); + if (r != MAILIMAP_NO_ERROR) + return r; + } + if (date_time != NULL) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_time_send(fd, date_time); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_literal_count_send(fd, literal_size); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + astring = 1*ASTRING-CHAR / string + +=> ASTRING-CHAR = ATOM-CHAR / resp-specials +*/ + +static int is_atom(const char * str) +{ + if (* str == '\0') + return 0; + + while (* str != '\0') { + unsigned char uch = (unsigned char) * str; + + if (uch != '-') { + if (!isalnum(uch)) + return 0; + } + + str ++; + } + + return 1; +} + +int mailimap_astring_send(mailstream * fd, const char * astring) +{ + /* + workaround for buggy Courier-IMAP that does not accept + quoted-strings for fields name but prefer atoms. + */ + if (is_atom(astring)) + return mailimap_atom_send(fd, astring); + else + return mailimap_quoted_send(fd, astring); +} + +/* +=> atom = 1*ATOM-CHAR +*/ + +static int mailimap_atom_send(mailstream * fd, const char * atom) +{ + return mailimap_token_send(fd, atom); +} + +/* +=> ATOM-CHAR = <any CHAR except atom-specials> +*/ + +/* +=> atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / + quoted-specials / resp-specials +*/ + +/* +=> authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64) +*/ + +int mailimap_authenticate_send(mailstream * fd, + const char * auth_type) +{ + int r; + + r = mailimap_token_send(fd, "AUTHENTICATE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_auth_type_send(fd, auth_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_authenticate_resp_send(mailstream * fd, + const char * base64) +{ + int r; + + r = mailimap_base64_send(fd, base64); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> auth-type = atom + ; Defined by [SASL] +*/ + +static int mailimap_auth_type_send(mailstream * fd, const char * auth_type) +{ + return mailimap_atom_send(fd, auth_type); +} + + +/* +=> base64 = *(4base64-char) [base64-terminal] +*/ + +static int mailimap_base64_send(mailstream * fd, const char * base64) +{ + return mailimap_token_send(fd, base64); +} + +/* +=> base64-char = ALPHA / DIGIT / "+" / "/" + ; Case-sensitive + + base64-terminal = (2base64-char "==") / (3base64-char "=") + + body = "(" (body-type-1part / body-type-mpart) ")" + + body-extension = nstring / number / + "(" body-extension *(SP body-extension) ")" + ; Future expansion. Client implementations + ; MUST accept body-extension fields. Server + ; implementations MUST NOT generate + ; body-extension fields except as defined by + ; future standard or standards-track + ; revisions of this specification. + + body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP + body-fld-enc SP body-fld-octets + + body-fld-desc = nstring + + body-fld-dsp = "(" string SP body-fld-param ")" / nil + + body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ + "QUOTED-PRINTABLE") DQUOTE) / string + + body-fld-id = nstring + + body-fld-lang = nstring / "(" string *(SP string) ")" + + body-fld-lines = number + + body-fld-md5 = nstring + + body-fld-octets = number + + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil + + body-type-1part = (body-type-basic / body-type-msg / body-type-text) + [SP body-ext-1part] + + body-type-basic = media-basic SP body-fields + ; MESSAGE subtype MUST NOT be "RFC822" + + body-type-mpart = 1*body SP media-subtype + [SP body-ext-mpart] + + body-type-msg = media-message SP body-fields SP envelope + SP body SP body-fld-lines + + body-type-text = media-text SP body-fields SP body-fld-lines + + capability = ("AUTH=" auth-type) / atom + ; New capabilities MUST begin with "X" or be + ; registered with IANA as standard or + ; standards-track + + capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1" + *(SP capability) + ; IMAP4rev1 servers which offer RFC 1730 + ; compatibility MUST list "IMAP4" as the first + ; capability. + + CHAR8 = %x01-ff + ; any OCTET except NUL, %x00 +*/ + +/* +=> command = tag SP (command-any / command-auth / command-nonauth / + command-select) CRLF + ; Modal based on state +*/ + +/* +=> command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command + ; Valid in all states +*/ + +int mailimap_capability_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "CAPABILITY"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_logout_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "LOGOUT"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_noop_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "NOOP"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> command-auth = append / create / delete / examine / list / lsub / + rename / select / status / subscribe / unsubscribe + ; Valid only in Authenticated or Selected state +*/ + +/* +=> command-nonauth = login / authenticate + ; Valid only when in Not Authenticated state +*/ + +/* +=> command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store / + uid / search + ; Valid only when in Selected state +*/ + +int mailimap_check_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "CHECK"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_close_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "CLOSE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_expunge_send(mailstream * fd) +{ + int r; + + r = mailimap_token_send(fd, "EXPUNGE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + continue-req = "+" SP (resp-text / base64) CRLF +*/ + +/* +=> copy = "COPY" SP set SP mailbox +*/ + +int mailimap_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "COPY"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_uid_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_copy_send(fd, set, mb); +} + +/* +=> create = "CREATE" SP mailbox + ; Use of INBOX gives a NO error +*/ + +int mailimap_create_send(mailstream * fd, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "CREATE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date = date-text / DQUOTE date-text DQUOTE +*/ + +static int mailimap_date_send(mailstream * fd, + struct mailimap_date * date) +{ + int r; + + r = mailimap_date_day_send(fd, date->dt_day); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_month_send(fd, date->dt_month); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_year_send(fd, date->dt_year); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date-day = 1*2DIGIT + ; Day of month +*/ + +static int mailimap_date_day_send(mailstream * fd, int day) +{ + return mailimap_number_send(fd, day); +} + +/* +=> date-day-fixed = (SP DIGIT) / 2DIGIT + ; Fixed-format version of date-day +*/ + +static int mailimap_date_day_fixed_send(mailstream * fd, int day) +{ + int r; + + if (day < 10) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_number_send(fd, day); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; + } + else + return mailimap_number_send(fd, day); +} + +/* +=> date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / + "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" +*/ + +static int mailimap_date_month_send(mailstream * fd, int month) +{ + const char * name; + int r; + + name = mailimap_month_get_token_str(month); + + if (name == NULL) + return MAILIMAP_ERROR_INVAL; + + r = mailimap_token_send(fd, name); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date-text = date-day "-" date-month "-" date-year +*/ + +/* +static gboolean mailimap_date_text_send(mailstream * fd, + struct mailimap_date_text * date_text) +{ + if (!mailimap_date_day_send(fd, date_text->day)) + return FALSE; + if (!mailimap_char_send(fd, '-')) + return FALSE; + if (!mailimap_date_month_send(fd, date_text->month)) + return FALSE; + if (!mailimap_char_send(fd, '-')) + return FALSE; + if (!mailimap_date_year_send(fd, date_text->year)) + return FALSE; + + return TRUE; +} +*/ + +/* +=> date-year = 4DIGIT +*/ + +static int mailimap_fixed_digit_send(mailstream * fd, + int num, int count) +{ + int r; + + if (count == 0) + return MAILIMAP_NO_ERROR; + + r = mailimap_fixed_digit_send(fd, num / 10, count - 1); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_digit_send(fd, num % 10); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +static int mailimap_date_year_send(mailstream * fd, int year) +{ + int r; + + r = mailimap_fixed_digit_send(fd, year, 4); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> date-time = DQUOTE date-day-fixed "-" date-month "-" date-year + SP time SP zone DQUOTE +*/ + +static int +mailimap_date_time_send(mailstream * fd, + struct mailimap_date_time * date_time) +{ + int r; + + r = mailimap_date_day_fixed_send(fd, date_time->dt_day); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_month_send(fd, date_time->dt_month); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_date_year_send(fd, date_time->dt_month); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fixed_digit_send(fd, date_time->dt_hour, 2); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ':'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fixed_digit_send(fd, date_time->dt_min, 2); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ':'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fixed_digit_send(fd, date_time->dt_sec, 2); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> delete = "DELETE" SP mailbox + ; Use of INBOX gives a NO error +*/ + +int mailimap_delete_send(mailstream * fd, const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "DELETE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + +digit + +digit-nz = %x31-39 + ; 1-9 +*/ + +static int mailimap_digit_send(mailstream * fd, int digit) +{ + return mailimap_char_send(fd, digit + '0'); +} + + +/* + envelope = "(" env-date SP env-subject SP env-from SP env-sender SP + env-reply-to SP env-to SP env-cc SP env-bcc SP + env-in-reply-to SP env-message-id ")" + + env-bcc = "(" 1*address ")" / nil + + env-cc = "(" 1*address ")" / nil + + env-date = nstring + + env-from = "(" 1*address ")" / nil + + env-in-reply-to = nstring + + env-message-id = nstring + + env-reply-to = "(" 1*address ")" / nil + + env-sender = "(" 1*address ")" / nil + + env-subject = nstring + + env-to = "(" 1*address ")" / nil +*/ + +/* +=> examine = "EXAMINE" SP mailbox +*/ + +int mailimap_examine_send(mailstream * fd, const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "EXAMINE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att / + "(" fetch-att *(SP fetch-att) ")") +*/ + +static int +mailimap_fetch_att_list_send(mailstream * fd, clist * fetch_att_list); + +static int +mailimap_fetch_type_send(mailstream * fd, + struct mailimap_fetch_type * fetch_type) +{ + switch (fetch_type->ft_type) { + case MAILIMAP_FETCH_TYPE_ALL: + return mailimap_token_send(fd, "ALL"); + case MAILIMAP_FETCH_TYPE_FULL: + return mailimap_token_send(fd, "FULL"); + case MAILIMAP_FETCH_TYPE_FAST: + return mailimap_token_send(fd, "FAST"); + case MAILIMAP_FETCH_TYPE_FETCH_ATT: + return mailimap_fetch_att_send(fd, fetch_type->ft_data.ft_fetch_att); + case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST: + return mailimap_fetch_att_list_send(fd, + fetch_type->ft_data.ft_fetch_att_list); + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + +int mailimap_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type) +{ + int r; + + r = mailimap_token_send(fd, "FETCH"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_fetch_type_send(fd, fetch_type); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_uid_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_fetch_send(fd, set, fetch_type); +} + +/* currently porting */ + +static int +mailimap_fetch_att_list_send(mailstream * fd, clist * fetch_att_list) +{ + int r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_send(fd, fetch_att_list, + (mailimap_struct_sender *) + mailimap_fetch_att_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" / + "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] / + "BODY" ["STRUCTURE"] / "UID" / + "BODY" [".PEEK"] section ["<" number "." nz-number ">"] +*/ + +static int mailimap_fetch_att_send(mailstream * fd, + struct mailimap_fetch_att * fetch_att) +{ + int r; + + switch(fetch_att->att_type) { + case MAILIMAP_FETCH_ATT_ENVELOPE: + return mailimap_token_send(fd, "ENVELOPE"); + + case MAILIMAP_FETCH_ATT_FLAGS: + return mailimap_token_send(fd, "FLAGS"); + + case MAILIMAP_FETCH_ATT_INTERNALDATE: + return mailimap_token_send(fd, "INTERNALDATE"); + + case MAILIMAP_FETCH_ATT_RFC822: + return mailimap_token_send(fd, "RFC822"); + + case MAILIMAP_FETCH_ATT_RFC822_HEADER: + return mailimap_token_send(fd, "RFC822.HEADER"); + + case MAILIMAP_FETCH_ATT_RFC822_SIZE: + return mailimap_token_send(fd, "RFC822.SIZE"); + + case MAILIMAP_FETCH_ATT_RFC822_TEXT: + return mailimap_token_send(fd, "RFC822.TEXT"); + + case MAILIMAP_FETCH_ATT_BODY: + return mailimap_token_send(fd, "BODY"); + + case MAILIMAP_FETCH_ATT_BODYSTRUCTURE: + return mailimap_token_send(fd, "BODYSTRUCTURE"); + + case MAILIMAP_FETCH_ATT_UID: + return mailimap_token_send(fd, "UID"); + + case MAILIMAP_FETCH_ATT_BODY_SECTION: + + r = mailimap_token_send(fd, "BODY"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_section_send(fd, fetch_att->att_section); + if (r != MAILIMAP_NO_ERROR) + return r; + if (fetch_att->att_size != 0) { + r = mailimap_char_send(fd, '<'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_offset); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '.'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_size); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '>'); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + return MAILIMAP_NO_ERROR; + + case MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION: + r = mailimap_token_send(fd, "BODY.PEEK"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_section_send(fd, fetch_att->att_section); + if (r != MAILIMAP_NO_ERROR) + return r; + if (fetch_att->att_size != 0) { + r = mailimap_char_send(fd, '<'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_offset); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '.'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, fetch_att->att_size); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, '>'); + if (r != MAILIMAP_NO_ERROR) + return r; + } + return MAILIMAP_NO_ERROR; + + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + +/* +=> flag = "\Answered" / "\Flagged" / "\Deleted" / + "\Seen" / "\Draft" / flag-keyword / flag-extension + ; Does not include "\Recent" +*/ + +/* +enum { + FLAG_ANSWERED, + FLAG_FLAGGED, + FLAG_DELETED, + FLAG_SEEN, + FLAG_DRAFT, + FLAG_KEYWORD, + FLAG_EXTENSION +}; + +struct mailimap_flag { + gint type; + gchar * flag_keyword; + gchar * flag_extension; +}; +*/ + +static int mailimap_flag_send(mailstream * fd, + struct mailimap_flag * flag) +{ + switch(flag->fl_type) { + case MAILIMAP_FLAG_ANSWERED: + return mailimap_token_send(fd, "\\Answered"); + case MAILIMAP_FLAG_FLAGGED: + return mailimap_token_send(fd, "\\Flagged"); + case MAILIMAP_FLAG_DELETED: + return mailimap_token_send(fd, "\\Deleted"); + case MAILIMAP_FLAG_SEEN: + return mailimap_token_send(fd, "\\Seen"); + case MAILIMAP_FLAG_DRAFT: + return mailimap_token_send(fd, "\\Draft"); + case MAILIMAP_FLAG_KEYWORD: + return mailimap_flag_keyword_send(fd, flag->fl_data.fl_keyword); + case MAILIMAP_FLAG_EXTENSION: + return mailimap_flag_extension_send(fd, flag->fl_data.fl_extension); + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + + +/* +=> flag-extension = "\" atom + ; Future expansion. Client implementations + ; MUST accept flag-extension flags. Server + ; implementations MUST NOT generate + ; flag-extension flags except as defined by + ; future standard or standards-track + ; revisions of this specification. +*/ + +static int mailimap_flag_extension_send(mailstream * fd, + const char * flag_extension) +{ + int r; + + r = mailimap_char_send(fd, '\\'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_atom_send(fd, flag_extension); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + flag-fetch = flag / "\Recent" +*/ + +/* +=> flag-keyword = atom +*/ + +static int mailimap_flag_keyword_send(mailstream * fd, + const char * flag_keyword) +{ + return mailimap_token_send(fd, flag_keyword); +} + +/* +=> flag-list = "(" [flag *(SP flag)] ")" +*/ + +static int mailimap_flag_list_send(mailstream * fd, + struct mailimap_flag_list * flag_list) +{ + int r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (flag_list->fl_list != NULL) { + r = mailimap_struct_spaced_list_send(fd, flag_list->fl_list, + (mailimap_struct_sender *) mailimap_flag_send); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + flag-perm = flag / "\*" + + greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF +*/ + +/* +=> header-fld-name = astring +*/ + +static int mailimap_header_fld_name_send(mailstream * fd, const char * header) +{ + return mailimap_astring_send(fd, header); +} + +/* +=> header-list = "(" header-fld-name *(SP header-fld-name) ")" +*/ + +static int +mailimap_header_list_send(mailstream * fd, + struct mailimap_header_list * header_list) +{ + int r; + + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_send(fd, header_list->hdr_list, + (mailimap_struct_sender *) mailimap_header_fld_name_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> list = "LIST" SP mailbox SP list-mailbox +*/ + +int mailimap_list_send(mailstream * fd, + const char * mb, + const char * list_mb) +{ + int r; + + r = mailimap_token_send(fd, "LIST"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_mailbox_send(fd, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> list-mailbox = 1*list-char / string +*/ + +int +mailimap_list_mailbox_send(mailstream * fd, const char * pattern) +{ + return mailimap_quoted_send(fd, pattern); +} + +/* + list-char = ATOM-CHAR / list-wildcards / resp-specials + + list-wildcards = "%" / "*" +*/ + +/* +=> literal = "{" number "}" CRLF *CHAR8 + ; Number represents the number of CHAR8s +*/ + +int +mailimap_literal_send(mailstream * fd, const char * literal, + size_t progr_rate, + progress_function * progr_fun) +{ + size_t len; + uint32_t literal_len; + int r; + + len = strlen(literal); + literal_len = mailstream_get_data_crlf_size(literal, len); + + r = mailimap_literal_count_send(fd, literal_len); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_literal_data_send(fd, literal, len, progr_rate, progr_fun); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + "{" number "}" CRLF +*/ + +int +mailimap_literal_count_send(mailstream * fd, uint32_t count) +{ + int r; + + r = mailimap_char_send(fd, '{'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_number_send(fd, count); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '}'); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + *CHAR8 +*/ + +int +mailimap_literal_data_send(mailstream * fd, const char * literal, uint32_t len, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + + r = mailimap_sized_token_send(fd, literal, len); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + + +/* +=> login = "LOGIN" SP userid SP password +*/ + +int mailimap_login_send(mailstream * fd, + const char * userid, const char * password) +{ + int r; + + r = mailimap_token_send(fd, "LOGIN"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_userid_send(fd, userid); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_password_send(fd, password); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> lsub = "LSUB" SP mailbox SP list-mailbox +*/ + +int mailimap_lsub_send(mailstream * fd, + const char * mb, const char * list_mb) +{ + int r; + + r = mailimap_token_send(fd, "LSUB"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_list_mailbox_send(fd, list_mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + mailbox = "INBOX" / astring + ; INBOX is case-insensitive. All case variants of + ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX + ; not as an astring. An astring which consists of + ; the case-insensitive sequence "I" "N" "B" "O" "X" + ; is considered to be INBOX and not an astring. + ; Refer to section 5.1 for further + ; semantic details of mailbox names. +*/ + +int mailimap_mailbox_send(mailstream * fd, const char * mb) +{ + return mailimap_astring_send(fd, mb); +} + +/* + mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / + "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" / + number SP "EXISTS" / number SP "RECENT" + + mailbox-list = "(" [mbx-list-flags] ")" SP + (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox + + mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag + *(SP mbx-list-oflag) / + mbx-list-oflag *(SP mbx-list-oflag) + + mbx-list-oflag = "\Noinferiors" / flag-extension + ; Other flags; multiple possible per LIST response + + mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked" + ; Selectability flags; only one per LIST response + + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] + + media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE + ; Defined in [MIME-IMT] + + media-subtype = string + ; Defined in [MIME-IMT] + + media-text = DQUOTE "TEXT" DQUOTE SP media-subtype + ; Defined in [MIME-IMT] + + message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att)) + + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" + + msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")" + ; MAY change for a message + + msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / + "RFC822" [".HEADER" / ".TEXT"] SP nstring / + "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / + "BODY" section ["<" number ">"] SP nstring / + "UID" SP uniqueid + ; MUST NOT change for a message + + nil = "NIL" + + nstring = string / nil +*/ + +/* +=> number = 1*DIGIT + ; Unsigned 32-bit integer + ; (0 <= n < 4,294,967,296) +*/ + +/* + nz-number = digit-nz *DIGIT + ; Non-zero unsigned 32-bit integer + ; (0 < n < 4,294,967,296) +*/ + +static int mailimap_number_send(mailstream * fd, uint32_t number) +{ + int r; + + if (number / 10 != 0) { + r = mailimap_number_send(fd, number / 10); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_digit_send(fd, number % 10); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> password = astring +*/ + +static int mailimap_password_send(mailstream * fd, const char * pass) +{ + return mailimap_astring_send(fd, pass); +} + +/* +=> quoted = DQUOTE *QUOTED-CHAR DQUOTE + +=> QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> / + "\" quoted-specials + +=> quoted-specials = DQUOTE / "\" +*/ + +static int is_quoted_specials(char ch) +{ + return (ch == '\"') || (ch == '\\'); +} + +static int mailimap_quoted_char_send(mailstream * fd, char ch) +{ + int r; + + if (is_quoted_specials(ch)) { + r = mailimap_char_send(fd, '\\'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, ch); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; + } + else + return mailimap_char_send(fd, ch); +} + +int mailimap_quoted_send(mailstream * fd, const char * quoted) +{ + const char * pos; + int r; + + pos = quoted; + + r = mailimap_dquote_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + while (* pos != 0) { + r = mailimap_quoted_char_send(fd, * pos); + if (r != MAILIMAP_NO_ERROR) + return r; + pos ++; + } + + r = mailimap_dquote_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> rename = "RENAME" SP mailbox SP mailbox + ; Use of INBOX as a destination gives a NO error +*/ + +int mailimap_rename_send(mailstream * fd, const char * mb, + const char * new_name) +{ + int r; + + r = mailimap_token_send(fd, "RENAME"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, new_name); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + response = *(continue-req / response-data) response-done + + response-data = "*" SP (resp-cond-state / resp-cond-bye / + mailbox-data / message-data / capability-data) CRLF + + response-done = response-tagged / response-fatal + + response-fatal = "*" SP resp-cond-bye CRLF + ; Server closes connection immediately + + response-tagged = tag SP resp-cond-state CRLF + + resp-cond-auth = ("OK" / "PREAUTH") SP resp-text + ; Authentication condition + + resp-cond-bye = "BYE" SP resp-text + + resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text + ; Status condition + + resp-specials = "]" + + resp-text = ["[" resp-text-code "]" SP] text + + resp-text-code = "ALERT" / + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / + capability-data / "PARSE" / + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / + "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / + "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number / + atom [SP 1*<any TEXT-CHAR except "]">] +*/ + +/* +=> search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key) + ; CHARSET argument to MUST be registered with IANA +*/ + +int +mailimap_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key) +{ + int r; + + r = mailimap_token_send(fd, "SEARCH"); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (charset != NULL) { + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_token_send(fd, "CHARSET"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, charset); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_search_key_send(fd, key); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_uid_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_search_send(fd, charset, key); +} + + +/* +=> search-key = "ALL" / "ANSWERED" / "BCC" SP astring / + "BEFORE" SP date / "BODY" SP astring / + "CC" SP astring / "DELETED" / "FLAGGED" / + "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" / + "OLD" / "ON" SP date / "RECENT" / "SEEN" / + "SINCE" SP date / "SUBJECT" SP astring / + "TEXT" SP astring / "TO" SP astring / + "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / + "UNKEYWORD" SP flag-keyword / "UNSEEN" / + ; Above this line were in [IMAP2] + "DRAFT" / "HEADER" SP header-fld-name SP astring / + "LARGER" SP number / "NOT" SP search-key / + "OR" SP search-key SP search-key / + "SENTBEFORE" SP date / "SENTON" SP date / + "SENTSINCE" SP date / "SMALLER" SP number / + "UID" SP set / "UNDRAFT" / set / + "(" search-key *(SP search-key) ")" +*/ + + +static int mailimap_search_key_send(mailstream * fd, + struct mailimap_search_key * key) +{ + int r; + + switch (key->sk_type) { + + case MAILIMAP_SEARCH_KEY_ALL: + return mailimap_token_send(fd, "ALL"); + + case MAILIMAP_SEARCH_KEY_ANSWERED: + return mailimap_token_send(fd, "ANSWERED"); + + case MAILIMAP_SEARCH_KEY_BCC: + r = mailimap_token_send(fd, "BCC"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_bcc); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_BEFORE: + r = mailimap_token_send(fd, "BEFORE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_before); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_BODY: + r = mailimap_token_send(fd, "BODY"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_body); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_CC: + r = mailimap_token_send(fd, "CC"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_cc); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_DELETED: + return mailimap_token_send(fd, "DELETED"); + + case MAILIMAP_SEARCH_KEY_FLAGGED: + return mailimap_token_send(fd, "FLAGGED"); + + case MAILIMAP_SEARCH_KEY_FROM: + r = mailimap_token_send(fd, "FROM"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_from); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_KEYWORD: + r = mailimap_token_send(fd, "KEYWORD"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_flag_keyword_send(fd, key->sk_data.sk_keyword); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_NEW: + return mailimap_token_send(fd, "NEW"); + + case MAILIMAP_SEARCH_KEY_OLD: + return mailimap_token_send(fd, "OLD"); + + case MAILIMAP_SEARCH_KEY_ON: + r = mailimap_token_send(fd, "ON"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_on); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_RECENT: + return mailimap_token_send(fd, "RECENT"); + + case MAILIMAP_SEARCH_KEY_SEEN: + return mailimap_token_send(fd, "SEEN"); + + case MAILIMAP_SEARCH_KEY_SINCE: + r = mailimap_token_send(fd, "SINCE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_since); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SUBJECT: + r = mailimap_token_send(fd, "SUBJECT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_subject); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_TEXT: + r = mailimap_token_send(fd, "TEXT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_text); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_TO: + r = mailimap_token_send(fd, "TO"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, key->sk_data.sk_text); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UNANSWERED: + return mailimap_token_send(fd, "UNANSWERED"); + + case MAILIMAP_SEARCH_KEY_UNDELETED: + return mailimap_token_send(fd, "UNDELETED"); + + case MAILIMAP_SEARCH_KEY_UNFLAGGED: + return mailimap_token_send(fd, "UNFLAGGED"); + + case MAILIMAP_SEARCH_KEY_UNKEYWORD: + r = mailimap_token_send(fd, "UNKEYWORD"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_flag_keyword_send(fd, key->sk_data.sk_keyword); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UNSEEN: + return mailimap_token_send(fd, "UNSEEN"); + + case MAILIMAP_SEARCH_KEY_DRAFT: + return mailimap_token_send(fd, "DRAFT"); + + case MAILIMAP_SEARCH_KEY_HEADER: + r = mailimap_token_send(fd, "HEADER"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_header_fld_name_send(fd, + key->sk_data.sk_header.sk_header_name); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_astring_send(fd, + key->sk_data.sk_header.sk_header_value); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_LARGER: + r = mailimap_token_send(fd, "LARGER"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, key->sk_data.sk_larger); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_NOT: + r = mailimap_token_send(fd, "NOT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_search_key_send(fd, key->sk_data.sk_not); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_OR: + r = mailimap_token_send(fd, "OR"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_search_key_send(fd, key->sk_data.sk_or.sk_or1); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_search_key_send(fd, key->sk_data.sk_or.sk_or2); + if (r != MAILIMAP_NO_ERROR) + return r; + return TRUE; + + case MAILIMAP_SEARCH_KEY_SENTBEFORE: + r = mailimap_token_send(fd, "SENTBEFORE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_sentbefore); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SENTON: + r = mailimap_token_send(fd, "SENTON"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_senton); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SENTSINCE: + r = mailimap_token_send(fd, "SENTSINCE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_date_send(fd, key->sk_data.sk_sentsince); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_SMALLER: + r = mailimap_token_send(fd, "SMALLER"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_number_send(fd, key->sk_data.sk_smaller); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UID: + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_set_send(fd, key->sk_data.sk_set); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SEARCH_KEY_UNDRAFT: + return mailimap_token_send(fd, "UNDRAFT"); + + case MAILIMAP_SEARCH_KEY_SET: + return mailimap_set_send(fd, key->sk_data.sk_set); + + case MAILIMAP_SEARCH_KEY_MULTIPLE: + r = mailimap_oparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_struct_spaced_list_send(fd, key->sk_data.sk_multiple, + (mailimap_struct_sender *) + mailimap_search_key_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_cparenth_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; + default: + /* should not happend */ + return MAILIMAP_ERROR_INVAL; + } +} + +/* +=> section = "[" [section-spec] "]" +*/ + +static int +mailimap_section_send(mailstream * fd, + struct mailimap_section * section) +{ + int r; + + r = mailimap_char_send(fd, '['); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (section != NULL) { + if (section->sec_spec != NULL) { + r = mailimap_section_spec_send(fd, section->sec_spec); + if (r != MAILIMAP_NO_ERROR) + return r; + } + } + + r = mailimap_char_send(fd, ']'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / + "TEXT" + ; top-level or MESSAGE/RFC822 part +*/ + +static int +mailimap_section_msgtext_send(mailstream * fd, + struct mailimap_section_msgtext * + section_msgtext) +{ + int r; + + switch (section_msgtext->sec_type) { + case MAILIMAP_SECTION_MSGTEXT_HEADER: + return mailimap_token_send(fd, "HEADER"); + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS: + r = mailimap_token_send(fd, "HEADER.FIELDS"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_header_list_send(fd, section_msgtext->sec_header_list); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT: + r = mailimap_token_send(fd, "HEADER.FIELDS.NOT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_header_list_send(fd, section_msgtext->sec_header_list); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + + case MAILIMAP_SECTION_MSGTEXT_TEXT: + return mailimap_token_send(fd, "TEXT"); + + default: + /* should not happend */ + return MAILIMAP_ERROR_INVAL; + } +} + +/* +=> section-part = nz-number *("." nz-number) + ; body part nesting +*/ + +static int +mailimap_pnumber_send(mailstream * fd, uint32_t * pnumber) +{ + return mailimap_number_send(fd, * pnumber); +} + +static int +mailimap_section_part_send(mailstream * fd, + struct mailimap_section_part * section) +{ + int r; + + r = mailimap_struct_list_send(fd, section->sec_id, '.', + (mailimap_struct_sender *) mailimap_pnumber_send); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> section-spec = section-msgtext / (section-part ["." section-text]) +*/ + +static int +mailimap_section_spec_send(mailstream * fd, + struct mailimap_section_spec * section_spec) +{ + int r; + + switch (section_spec->sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + return mailimap_section_msgtext_send(fd, + section_spec->sec_data.sec_msgtext); + + case MAILIMAP_SECTION_SPEC_SECTION_PART: + r = mailimap_section_part_send(fd, section_spec->sec_data.sec_part); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (section_spec->sec_text != NULL) { + r = mailimap_char_send(fd, '.'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_section_text_send(fd, + section_spec->sec_text); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + return MAILIMAP_NO_ERROR; + + default: + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } +} + +/* +=> section-text = section-msgtext / "MIME" + ; text other than actual body part (headers, etc.) +*/ + +static int +mailimap_section_text_send(mailstream * fd, + struct mailimap_section_text * section_text) +{ + switch (section_text->sec_type) { + case MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT: + return mailimap_section_msgtext_send(fd, section_text->sec_msgtext); + + case MAILIMAP_SECTION_TEXT_MIME: + return mailimap_token_send(fd, "MIME"); + + default: + /* should not happen */ + return MAILIMAP_NO_ERROR; + } +} + +/* +=> select = "SELECT" SP mailbox +*/ + +int +mailimap_select_send(mailstream * fd, const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "SELECT"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> sequence-num = nz-number / "*" + ; * is the largest number in use. For message + ; sequence numbers, it is the number of messages + ; in the mailbox. For unique identifiers, it is + ; the unique identifier of the last message in + ; the mailbox. +*/ + +/* if sequence_num == 0 then "*" */ + +static int +mailimap_sequence_num_send(mailstream * fd, uint32_t sequence_num) +{ + if (sequence_num == 0) + return mailimap_char_send(fd, '*'); + else + return mailimap_number_send(fd, sequence_num); +} + +/* +=> set = sequence-num / (sequence-num ":" sequence-num) / + (set "," set) + ; Identifies a set of messages. For message + ; sequence numbers, these are consecutive + ; numbers from 1 to the number of messages in + ; the mailbox + ; Comma delimits individual numbers, colon + ; delimits between two numbers inclusive. + ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13, + ; 14,15 for a mailbox with 15 messages. +*/ + +static int mailimap_set_item_send(mailstream * fd, + struct mailimap_set_item * item) +{ + int r; + + if (item->set_first == item->set_last) + return mailimap_sequence_num_send(fd, item->set_first); + else { + r = mailimap_sequence_num_send(fd, item->set_first); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_char_send(fd, ':'); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_sequence_num_send(fd, item->set_last); + if (r != MAILIMAP_NO_ERROR) + return r; + return MAILIMAP_NO_ERROR; + } +} + +int mailimap_set_send(mailstream * fd, + struct mailimap_set * set) +{ + return mailimap_struct_list_send(fd, set->set_list, ',', + (mailimap_struct_sender *) mailimap_set_item_send); +} + +/* +=> status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")" +*/ + +static int +mailimap_status_att_list_send(mailstream * fd, + struct mailimap_status_att_list * status_att_list) +{ + return mailimap_struct_spaced_list_send(fd, status_att_list->att_list, + (mailimap_struct_sender *) mailimap_status_att_send); +} + +int +mailimap_status_send(mailstream * fd, const char * mb, + struct mailimap_status_att_list * status_att_list) +{ + int r; + + r = mailimap_token_send(fd, "STATUS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, '('); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_status_att_list_send(fd, status_att_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_char_send(fd, ')'); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / + "UNSEEN" +*/ + + +static int mailimap_status_att_send(mailstream * fd, int * status_att) +{ + const char * token; + + token = mailimap_status_att_get_token_str(* status_att); + if (token == NULL) { + /* should not happen */ + return MAILIMAP_ERROR_INVAL; + } + + return mailimap_token_send(fd, token); +} + +/* +=> store = "STORE" SP set SP store-att-flags +*/ + +int +mailimap_store_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags) +{ + int r; + + r = mailimap_token_send(fd, "STORE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_store_att_flags_send(fd, store_att_flags); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int +mailimap_uid_store_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + return mailimap_store_send(fd, set, store_att_flags); +} + +/* +=> store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP + (flag-list / (flag *(SP flag))) +*/ + +static int +mailimap_store_att_flags_send(mailstream * fd, + struct mailimap_store_att_flags * store_flags) +{ + int r; + + switch (store_flags->fl_sign) { + case 1: + r = mailimap_char_send(fd, '+'); + if (r != MAILIMAP_NO_ERROR) + return r; + break; + case -1: + r = mailimap_char_send(fd, '-'); + if (r != MAILIMAP_NO_ERROR) + return r; + break; + } + + r = mailimap_token_send(fd, "FLAGS"); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (store_flags->fl_silent) { + r = mailimap_token_send(fd, ".SILENT"); + if (r != MAILIMAP_NO_ERROR) + return r; + } + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_flag_list_send(fd, store_flags->fl_flag_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* + string = quoted / literal +*/ + +/* +=> subscribe = "SUBSCRIBE" SP mailbox +*/ + +int mailimap_subscribe_send(mailstream * fd, const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "SUBSCRIBE"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +/* +=> tag = 1*<any ASTRING-CHAR except "+"> +*/ + +int mailimap_tag_send(mailstream * fd, const char * tag) +{ + return mailimap_token_send(fd, tag); +} + +/* + text = 1*TEXT-CHAR + + TEXT-CHAR = <any CHAR except CR and LF> + + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds +*/ + +/* +=> uid = "UID" SP (copy / fetch / search / store) + ; Unique identifiers used instead of message + ; sequence numbers + +functions uid_copy, uid_fetch ... +*/ + + +/* + uniqueid = nz-number + ; Strictly ascending +*/ + +/* +=> unsubscribe = "UNSUBSCRIBE" SP mailbox +*/ + +int mailimap_unsubscribe_send(mailstream * fd, + const char * mb) +{ + int r; + + r = mailimap_token_send(fd, "UNSUBSCRIBE"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_mailbox_send(fd, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_starttls_send(mailstream * fd) +{ + return mailimap_token_send(fd, "STARTTLS"); +} + +/* +=> userid = astring +*/ + +static int mailimap_userid_send(mailstream * fd, const char * user) +{ + return mailimap_astring_send(fd, user); +} + +/* + x-command = "X" atom <experimental command arguments> + + zone = ("+" / "-") 4DIGIT + ; Signed four-digit value of hhmm representing + ; hours and minutes east of Greenwich (that is, + ; the amount that the given time differs from + ; Universal Time). Subtracting the timezone + ; from the given time will give the UT form. + ; The Universal Time zone is "+0000". +*/ Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_sender.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_sender.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,186 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_sender.h,v 1.14 2006/10/20 00:13:30 hoa Exp $ + */ + +#ifndef MAILIMAP_SENDER_H + +#define MAILIMAP_SENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailimap_types.h" + +int mailimap_append_send(mailstream * fd, + const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + size_t literal_size); + +int mailimap_authenticate_send(mailstream * fd, + const char * auth_type); + +int mailimap_authenticate_resp_send(mailstream * fd, + const char * base64); + +int mailimap_noop_send(mailstream * fd); + +int mailimap_logout_send(mailstream * fd); + +int mailimap_capability_send(mailstream * fd); + +int mailimap_check_send(mailstream * fd); + +int mailimap_close_send(mailstream * fd); + +int mailimap_expunge_send(mailstream * fd); + +int mailimap_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb); + +int mailimap_uid_copy_send(mailstream * fd, + struct mailimap_set * set, + const char * mb); + +int mailimap_create_send(mailstream * fd, + const char * mb); + + +int mailimap_delete_send(mailstream * fd, const char * mb); + +int mailimap_examine_send(mailstream * fd, const char * mb); + +int +mailimap_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type); + +int +mailimap_uid_fetch_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_fetch_type * fetch_type); + +int mailimap_list_send(mailstream * fd, + const char * mb, const char * list_mb); + +int mailimap_login_send(mailstream * fd, + const char * userid, const char * password); + +int mailimap_lsub_send(mailstream * fd, + const char * mb, const char * list_mb); + +int mailimap_rename_send(mailstream * fd, const char * mb, + const char * new_name); + +int +mailimap_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key); + +int +mailimap_uid_search_send(mailstream * fd, const char * charset, + struct mailimap_search_key * key); + +int +mailimap_select_send(mailstream * fd, const char * mb); + +int +mailimap_status_send(mailstream * fd, const char * mb, + struct mailimap_status_att_list * status_att_list); + +int +mailimap_store_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +int +mailimap_uid_store_send(mailstream * fd, + struct mailimap_set * set, + struct mailimap_store_att_flags * store_att_flags); + +int mailimap_subscribe_send(mailstream * fd, const char * mb); + + +int mailimap_tag_send(mailstream * fd, const char * tag); + +int mailimap_unsubscribe_send(mailstream * fd, + const char * mb); + +int mailimap_crlf_send(mailstream * fd); + +int mailimap_space_send(mailstream * fd); + +int +mailimap_literal_send(mailstream * fd, const char * literal, + size_t progr_rate, + progress_function * progr_fun); + +int +mailimap_literal_count_send(mailstream * fd, uint32_t count); + +int +mailimap_literal_data_send(mailstream * fd, const char * literal, uint32_t len, + size_t progr_rate, + progress_function * progr_fun); + +int mailimap_starttls_send(mailstream * fd); + +int mailimap_token_send(mailstream * fd, const char * atom); + +int mailimap_quoted_send(mailstream * fd, const char * quoted); + +typedef int mailimap_struct_sender(mailstream * fd, void * data); + +int +mailimap_struct_spaced_list_send(mailstream * fd, clist * list, + mailimap_struct_sender * sender); + +int +mailimap_list_mailbox_send(mailstream * fd, const char * pattern); + +int mailimap_char_send(mailstream * fd, char ch); + +int mailimap_mailbox_send(mailstream * fd, const char * mb); + +int mailimap_astring_send(mailstream * fd, const char * astring); + +int mailimap_set_send(mailstream * fd, + struct mailimap_set * set); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_socket.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_socket.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,83 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_socket.c,v 1.16 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimap_socket.h" + +#include "mailimap.h" + +#include "connect.h" + +#include <stdlib.h> +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#define DEFAULT_IMAP_PORT 143 +#define SERVICE_NAME_IMAP "imap2" +#define SERVICE_TYPE_TCP "tcp" + +LIBETPAN_EXPORT +int mailimap_socket_connect(mailimap * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_IMAP, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_IMAP_PORT; + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return MAILIMAP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_socket_open(s); + if (stream == NULL) { + close(s); + return MAILIMAP_ERROR_MEMORY; + } + + return mailimap_connect(f, stream); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_socket.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_socket.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,57 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_socket.h,v 1.15 2006/05/22 13:39:41 hoa Exp $ + */ + +#ifndef MAILIMAP_SOCKET_H + +#define MAILIMAP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif + +#include <libetpan/mailimap_types.h> + +LIBETPAN_EXPORT +int mailimap_socket_connect(mailimap * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_ssl.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_ssl.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,82 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_ssl.c,v 1.14 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimap_ssl.h" + +#include "mailimap.h" + +#include "connect.h" + +#include <stdlib.h> +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#define DEFAULT_IMAPS_PORT 993 +#define SERVICE_NAME_IMAPS "imaps" +#define SERVICE_TYPE_TCP "tcp" + +int mailimap_ssl_connect(mailimap * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_IMAPS, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_IMAPS_PORT; + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return MAILIMAP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_ssl_open(s); + if (stream == NULL) { + close(s); + return MAILIMAP_ERROR_CONNECTION_REFUSED; + } + + return mailimap_connect(f, stream); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_ssl.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_ssl.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_ssl.h,v 1.14 2006/05/22 13:39:41 hoa Exp $ + */ + +#ifndef MAILIMAP_SSL_H + +#define MAILIMAP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif + +#include <libetpan/mailimap_types.h> + +int mailimap_ssl_connect(mailimap * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_types.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_types.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3001 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_types.c,v 1.26 2006/10/25 23:10:59 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimap_types.h" +#include "mmapstring.h" +#include "mail.h" +#include "mailimap_extension.h" + +#include <stdlib.h> +#include <stdio.h> + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + + + +/* from parser */ + + +uint32_t * mailimap_number_alloc_new(uint32_t number) +{ + uint32_t * pnumber; + + pnumber = malloc(sizeof(* pnumber)); + if (pnumber == NULL) + return NULL; + + * pnumber = number; + + return pnumber; +} + +void mailimap_number_alloc_free(uint32_t * pnumber) +{ + free(pnumber); +} + + +/* ************************************************************************* */ + + +struct mailimap_address * +mailimap_address_new(char * ad_personal_name, char * ad_source_route, + char * ad_mailbox_name, char * ad_host_name) +{ + struct mailimap_address * addr; + + addr = malloc(sizeof(* addr)); + if (addr == NULL) + return NULL; + + addr->ad_personal_name = ad_personal_name; + addr->ad_source_route = ad_source_route; + addr->ad_mailbox_name = ad_mailbox_name; + addr->ad_host_name = ad_host_name; + + return addr; +} + +void mailimap_address_free(struct mailimap_address * addr) +{ + mailimap_addr_host_free(addr->ad_host_name); + mailimap_addr_mailbox_free(addr->ad_mailbox_name); + mailimap_addr_adl_free(addr->ad_source_route); + mailimap_addr_name_free(addr->ad_personal_name); + free(addr); +} + +void mailimap_addr_host_free(char * addr_host) +{ + mailimap_nstring_free(addr_host); +} + +void mailimap_addr_mailbox_free(char * addr_mailbox) +{ + mailimap_nstring_free(addr_mailbox); +} + +void mailimap_addr_adl_free(char * addr_adl) +{ + mailimap_nstring_free(addr_adl); +} + +void mailimap_addr_name_free(char * addr_name) +{ + mailimap_nstring_free(addr_name); +} + + + + + +/* +struct mailimap_astring * +mailimap_astring_new(gint type, + gchar * atom_astring, + gchar * string) +{ + struct mailimap_astring * astring; + + astring = g_new(struct mailimap_astring, 1); + if (astring == NULL) + return FALSE; + + astring->type = type; + astring->atom_astring = atom_astring; + astring->string = string; + + return astring; +} + +void mailimap_astring_free(struct mailimap_astring * astring) +{ + if (astring->atom_astring) + mailimap_atom_astring_free(astring->atom_astring); + if (astring->string) + mailimap_string_free(astring->string); + free(astring); +} +*/ + +void mailimap_astring_free(char * astring) +{ + if (mmap_string_unref(astring) != 0) + free(astring); +} + +static void mailimap_custom_string_free(char * str) +{ + free(str); +} + + +void mailimap_atom_free(char * atom) +{ + free(atom); +} + + + + +void mailimap_auth_type_free(char * auth_type) +{ + mailimap_atom_free(auth_type); +} + + + + + +void mailimap_base64_free(char * base64) +{ + free(base64); +} + + + + +struct mailimap_body * +mailimap_body_new(int bd_type, + struct mailimap_body_type_1part * bd_body_1part, + struct mailimap_body_type_mpart * bd_body_mpart) +{ + struct mailimap_body * body; + + body = malloc(sizeof(* body)); + if (body == NULL) + return NULL; + + body->bd_type = bd_type; + switch (bd_type) { + case MAILIMAP_BODY_1PART: + body->bd_data.bd_body_1part = bd_body_1part; + break; + case MAILIMAP_BODY_MPART: + body->bd_data.bd_body_mpart = bd_body_mpart; + break; + } + + return body; +} + +void mailimap_body_free(struct mailimap_body * body) +{ + switch (body->bd_type) { + case MAILIMAP_BODY_1PART: + mailimap_body_type_1part_free(body->bd_data.bd_body_1part); + break; + case MAILIMAP_BODY_MPART: + mailimap_body_type_mpart_free(body->bd_data.bd_body_mpart); + break; + } + free(body); +} + + +struct mailimap_body_extension * +mailimap_body_extension_new(int ext_type, char * ext_nstring, + uint32_t ext_number, + clist * ext_body_extension_list) +{ + struct mailimap_body_extension * body_extension; + + body_extension = malloc(sizeof(* body_extension)); + if (body_extension == NULL) + return NULL; + + body_extension->ext_type = ext_type; + switch (ext_type) { + case MAILIMAP_BODY_EXTENSION_NSTRING: + body_extension->ext_data.ext_nstring = ext_nstring; + break; + case MAILIMAP_BODY_EXTENSION_NUMBER: + body_extension->ext_data.ext_number = ext_number; + break; + case MAILIMAP_BODY_EXTENSION_LIST: + body_extension->ext_data.ext_body_extension_list = ext_body_extension_list; + break; + } + + return body_extension; +} + +static void +mailimap_body_ext_list_free(clist * body_ext_list); + +void mailimap_body_extension_free(struct mailimap_body_extension * be) +{ + switch (be->ext_type) { + case MAILIMAP_BODY_EXTENSION_NSTRING: + mailimap_nstring_free(be->ext_data.ext_nstring); + break; + case MAILIMAP_BODY_EXTENSION_LIST: + mailimap_body_ext_list_free(be->ext_data.ext_body_extension_list); + break; + } + + free(be); +} + + +static void +mailimap_body_ext_list_free(clist * body_ext_list) +{ + clist_foreach(body_ext_list, (clist_func) mailimap_body_extension_free, + NULL); + clist_free(body_ext_list); +} + + +struct mailimap_body_ext_1part * +mailimap_body_ext_1part_new(char * bd_md5, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + clist * bd_extension_list) +{ + struct mailimap_body_ext_1part * body_ext_1part; + + body_ext_1part = malloc(sizeof(* body_ext_1part)); + if (body_ext_1part == NULL) + return NULL; + + body_ext_1part->bd_md5 = bd_md5; + body_ext_1part->bd_disposition = bd_disposition; + body_ext_1part->bd_language = bd_language; + body_ext_1part->bd_extension_list = bd_extension_list; + + return body_ext_1part; +} + +void +mailimap_body_ext_1part_free(struct mailimap_body_ext_1part * body_ext_1part) +{ + mailimap_body_fld_md5_free(body_ext_1part->bd_md5); + if (body_ext_1part->bd_disposition) + mailimap_body_fld_dsp_free(body_ext_1part->bd_disposition); + if (body_ext_1part->bd_language) + mailimap_body_fld_lang_free(body_ext_1part->bd_language); + if (body_ext_1part->bd_extension_list) + mailimap_body_ext_list_free(body_ext_1part->bd_extension_list); + + free(body_ext_1part); +} + +struct mailimap_body_ext_mpart * +mailimap_body_ext_mpart_new(struct mailimap_body_fld_param * bd_parameter, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + clist * bd_extension_list) +{ + struct mailimap_body_ext_mpart * body_ext_mpart; + + body_ext_mpart = malloc(sizeof(* body_ext_mpart)); + if (body_ext_mpart == NULL) + return NULL; + + body_ext_mpart->bd_parameter = bd_parameter; + body_ext_mpart->bd_disposition = bd_disposition; + body_ext_mpart->bd_language = bd_language; + body_ext_mpart->bd_extension_list = bd_extension_list; + + return body_ext_mpart; +} + +void +mailimap_body_ext_mpart_free(struct mailimap_body_ext_mpart * body_ext_mpart) +{ + if (body_ext_mpart->bd_parameter != NULL) + mailimap_body_fld_param_free(body_ext_mpart->bd_parameter); + if (body_ext_mpart->bd_disposition) + mailimap_body_fld_dsp_free(body_ext_mpart->bd_disposition); + if (body_ext_mpart->bd_language) + mailimap_body_fld_lang_free(body_ext_mpart->bd_language); + if (body_ext_mpart->bd_extension_list) + mailimap_body_ext_list_free(body_ext_mpart->bd_extension_list); + free(body_ext_mpart); +} + + +struct mailimap_body_fields * +mailimap_body_fields_new(struct mailimap_body_fld_param * bd_parameter, + char * bd_id, + char * bd_description, + struct mailimap_body_fld_enc * bd_encoding, + uint32_t bd_size) +{ + struct mailimap_body_fields * body_fields; + + body_fields = malloc(sizeof(* body_fields)); + if (body_fields == NULL) + return NULL; + body_fields->bd_parameter = bd_parameter; + body_fields->bd_id = bd_id; + body_fields->bd_description = bd_description; + body_fields->bd_encoding = bd_encoding; + body_fields->bd_size = bd_size; + + return body_fields; +} + +void +mailimap_body_fields_free(struct mailimap_body_fields * body_fields) +{ + if (body_fields->bd_parameter != NULL) + mailimap_body_fld_param_free(body_fields->bd_parameter); + mailimap_body_fld_id_free(body_fields->bd_id); + mailimap_body_fld_desc_free(body_fields->bd_description); + mailimap_body_fld_enc_free(body_fields->bd_encoding); + free(body_fields); +} + + + + + + +void mailimap_body_fld_desc_free(char * body_fld_desc) +{ + mailimap_nstring_free(body_fld_desc); +} + + + + +struct mailimap_body_fld_dsp * +mailimap_body_fld_dsp_new(char * dsp_type, + struct mailimap_body_fld_param * dsp_attributes) +{ + struct mailimap_body_fld_dsp * body_fld_dsp; + + body_fld_dsp = malloc(sizeof(* body_fld_dsp)); + if (body_fld_dsp == NULL) + return NULL; + + body_fld_dsp->dsp_type = dsp_type; + body_fld_dsp->dsp_attributes = dsp_attributes; + + return body_fld_dsp; +} + +void mailimap_body_fld_dsp_free(struct mailimap_body_fld_dsp * bfd) +{ + if (bfd->dsp_type != NULL) + mailimap_string_free(bfd->dsp_type); + if (bfd->dsp_attributes != NULL) + mailimap_body_fld_param_free(bfd->dsp_attributes); + free(bfd); +} + + + +struct mailimap_body_fld_enc * +mailimap_body_fld_enc_new(int enc_type, char * enc_value) +{ + struct mailimap_body_fld_enc * body_fld_enc; + + body_fld_enc = malloc(sizeof(* body_fld_enc)); + if (body_fld_enc == NULL) + return NULL; + + body_fld_enc->enc_type = enc_type; + body_fld_enc->enc_value = enc_value; + + return body_fld_enc; +} + +void mailimap_body_fld_enc_free(struct mailimap_body_fld_enc * bfe) +{ + if (bfe->enc_value) + mailimap_string_free(bfe->enc_value); + free(bfe); +} + + + +void mailimap_body_fld_id_free(char * body_fld_id) +{ + mailimap_nstring_free(body_fld_id); +} + + + +struct mailimap_body_fld_lang * +mailimap_body_fld_lang_new(int lg_type, char * lg_single, clist * lg_list) +{ + struct mailimap_body_fld_lang * fld_lang; + + fld_lang = malloc(sizeof(* fld_lang)); + if (fld_lang == NULL) + return NULL; + + fld_lang->lg_type = lg_type; + switch (lg_type) { + case MAILIMAP_BODY_FLD_LANG_SINGLE: + fld_lang->lg_data.lg_single = lg_single; + break; + case MAILIMAP_BODY_FLD_LANG_LIST: + fld_lang->lg_data.lg_list = lg_list; + break; + } + + return fld_lang; +} + +void +mailimap_body_fld_lang_free(struct mailimap_body_fld_lang * fld_lang) +{ + switch (fld_lang->lg_type) { + case MAILIMAP_BODY_FLD_LANG_SINGLE: + mailimap_nstring_free(fld_lang->lg_data.lg_single); + break; + case MAILIMAP_BODY_FLD_LANG_LIST: + clist_foreach(fld_lang->lg_data.lg_list, + (clist_func) mailimap_string_free, NULL); + clist_free(fld_lang->lg_data.lg_list); + break; + } + free(fld_lang); +} + + + +void mailimap_body_fld_md5_free(char * body_fld_md5) +{ + mailimap_nstring_free(body_fld_md5); +} + + + +struct mailimap_single_body_fld_param * +mailimap_single_body_fld_param_new(char * pa_name, char * pa_value) +{ + struct mailimap_single_body_fld_param * param; + + param = malloc(sizeof(* param)); + if (param == NULL) + return NULL; + param->pa_name = pa_name; + param->pa_value = pa_value; + + return param; +} + +void +mailimap_single_body_fld_param_free(struct mailimap_single_body_fld_param * p) +{ + mailimap_string_free(p->pa_name); + mailimap_string_free(p->pa_value); + free(p); +} + + +struct mailimap_body_fld_param * +mailimap_body_fld_param_new(clist * pa_list) +{ + struct mailimap_body_fld_param * fld_param; + + fld_param = malloc(sizeof(* fld_param)); + if (fld_param == NULL) + return NULL; + fld_param->pa_list = pa_list; + + return fld_param; +} + +void +mailimap_body_fld_param_free(struct mailimap_body_fld_param * fld_param) +{ + clist_foreach(fld_param->pa_list, + (clist_func) mailimap_single_body_fld_param_free, NULL); + clist_free(fld_param->pa_list); + free(fld_param); +} + + +struct mailimap_body_type_1part * +mailimap_body_type_1part_new(int bd_type, + struct mailimap_body_type_basic * bd_type_basic, + struct mailimap_body_type_msg * bd_type_msg, + struct mailimap_body_type_text * bd_type_text, + struct mailimap_body_ext_1part * bd_ext_1part) +{ + struct mailimap_body_type_1part * body_type_1part; + + body_type_1part = malloc(sizeof(* body_type_1part)); + if (body_type_1part == NULL) + return NULL; + + body_type_1part->bd_type = bd_type; + switch (bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + body_type_1part->bd_data.bd_type_basic = bd_type_basic; + break; + case MAILIMAP_BODY_TYPE_1PART_MSG: + body_type_1part->bd_data.bd_type_msg = bd_type_msg; + break; + case MAILIMAP_BODY_TYPE_1PART_TEXT: + body_type_1part->bd_data.bd_type_text = bd_type_text; + break; + } + body_type_1part->bd_ext_1part = bd_ext_1part; + + return body_type_1part; +} + +void +mailimap_body_type_1part_free(struct mailimap_body_type_1part * bt1p) +{ + switch (bt1p->bd_type) { + case MAILIMAP_BODY_TYPE_1PART_BASIC: + mailimap_body_type_basic_free(bt1p->bd_data.bd_type_basic); + break; + case MAILIMAP_BODY_TYPE_1PART_MSG: + mailimap_body_type_msg_free(bt1p->bd_data.bd_type_msg); + break; + case MAILIMAP_BODY_TYPE_1PART_TEXT: + mailimap_body_type_text_free(bt1p->bd_data.bd_type_text); + break; + } + if (bt1p->bd_ext_1part) + mailimap_body_ext_1part_free(bt1p->bd_ext_1part); + + free(bt1p); +} + + + +struct mailimap_body_type_basic * +mailimap_body_type_basic_new(struct mailimap_media_basic * bd_media_basic, + struct mailimap_body_fields * bd_fields) +{ + struct mailimap_body_type_basic * body_type_basic; + + body_type_basic = malloc(sizeof(* body_type_basic)); + if (body_type_basic == NULL) + return NULL; + + body_type_basic->bd_media_basic = bd_media_basic; + body_type_basic->bd_fields = bd_fields; + + return body_type_basic; +} + +void mailimap_body_type_basic_free(struct mailimap_body_type_basic * + body_type_basic) +{ + mailimap_media_basic_free(body_type_basic->bd_media_basic); + mailimap_body_fields_free(body_type_basic->bd_fields); + free(body_type_basic); +} + + +struct mailimap_body_type_mpart * +mailimap_body_type_mpart_new(clist * bd_list, char * bd_media_subtype, + struct mailimap_body_ext_mpart * bd_ext_mpart) +{ + struct mailimap_body_type_mpart * body_type_mpart; + + body_type_mpart = malloc(sizeof(* body_type_mpart)); + if (body_type_mpart == NULL) + return NULL; + + body_type_mpart->bd_list = bd_list; + body_type_mpart->bd_media_subtype = bd_media_subtype; + body_type_mpart->bd_ext_mpart = bd_ext_mpart; + + return body_type_mpart; +} + +void mailimap_body_type_mpart_free(struct mailimap_body_type_mpart * + body_type_mpart) +{ + clist_foreach(body_type_mpart->bd_list, + (clist_func) mailimap_body_free, NULL); + clist_free(body_type_mpart->bd_list); + mailimap_media_subtype_free(body_type_mpart->bd_media_subtype); + if (body_type_mpart->bd_ext_mpart) + mailimap_body_ext_mpart_free(body_type_mpart->bd_ext_mpart); + + free(body_type_mpart); +} + + +struct mailimap_body_type_msg * +mailimap_body_type_msg_new(struct mailimap_body_fields * bd_fields, + struct mailimap_envelope * bd_envelope, + struct mailimap_body * bd_body, + uint32_t bd_lines) +{ + struct mailimap_body_type_msg * body_type_msg; + + body_type_msg = malloc(sizeof(* body_type_msg)); + if (body_type_msg == NULL) + return NULL; + + body_type_msg->bd_fields = bd_fields; + body_type_msg->bd_envelope = bd_envelope; + body_type_msg->bd_body = bd_body; + body_type_msg->bd_lines = bd_lines; + + return body_type_msg; +} + +void +mailimap_body_type_msg_free(struct mailimap_body_type_msg * body_type_msg) +{ + mailimap_body_fields_free(body_type_msg->bd_fields); + mailimap_envelope_free(body_type_msg->bd_envelope); + mailimap_body_free(body_type_msg->bd_body); + free(body_type_msg); +} + + + +struct mailimap_body_type_text * +mailimap_body_type_text_new(char * bd_media_text, + struct mailimap_body_fields * bd_fields, + uint32_t bd_lines) +{ + struct mailimap_body_type_text * body_type_text; + + body_type_text = malloc(sizeof(* body_type_text)); + if (body_type_text == NULL) + return NULL; + + body_type_text->bd_media_text = bd_media_text; + body_type_text->bd_fields = bd_fields; + body_type_text->bd_lines = bd_lines; + + return body_type_text; +} + +void +mailimap_body_type_text_free(struct mailimap_body_type_text * body_type_text) +{ + mailimap_media_text_free(body_type_text->bd_media_text); + mailimap_body_fields_free(body_type_text->bd_fields); + free(body_type_text); +} + + + +struct mailimap_capability * +mailimap_capability_new(int cap_type, char * cap_auth_type, char * cap_name) +{ + struct mailimap_capability * cap; + + cap = malloc(sizeof(* cap)); + if (cap == NULL) + return NULL; + cap->cap_type = cap_type; + switch (cap_type) { + case MAILIMAP_CAPABILITY_AUTH_TYPE: + cap->cap_data.cap_auth_type = cap_auth_type; + break; + case MAILIMAP_CAPABILITY_NAME: + cap->cap_data.cap_name = cap_name; + break; + } + + return cap; +} + +void mailimap_capability_free(struct mailimap_capability * c) +{ + switch (c->cap_type) { + case MAILIMAP_CAPABILITY_AUTH_TYPE: + free(c->cap_data.cap_auth_type); + break; + case MAILIMAP_CAPABILITY_NAME: + free(c->cap_data.cap_name); + break; + } + free(c); +} + + +struct mailimap_capability_data * +mailimap_capability_data_new(clist * cap_list) +{ + struct mailimap_capability_data * cap_data; + + cap_data = malloc(sizeof(* cap_data)); + if (cap_data == NULL) + return NULL; + + cap_data->cap_list = cap_list; + + return cap_data; +} + +void +mailimap_capability_data_free(struct mailimap_capability_data * cap_data) +{ + if (cap_data->cap_list) { + clist_foreach(cap_data->cap_list, + (clist_func) mailimap_capability_free, NULL); + clist_free(cap_data->cap_list); + } + free(cap_data); +} + + + + +struct mailimap_continue_req * +mailimap_continue_req_new(int cr_type, struct mailimap_resp_text * cr_text, + char * cr_base64) +{ + struct mailimap_continue_req * cont_req; + + cont_req = malloc(sizeof(* cont_req)); + if (cont_req == NULL) + return NULL; + cont_req->cr_type = cr_type; + switch (cr_type) { + case MAILIMAP_CONTINUE_REQ_TEXT: + cont_req->cr_data.cr_text = cr_text; + break; + case MAILIMAP_CONTINUE_REQ_BASE64: + cont_req->cr_data.cr_base64 = cr_base64; + break; + } + + return cont_req; +} + +void mailimap_continue_req_free(struct mailimap_continue_req * cont_req) +{ + switch (cont_req->cr_type) { + case MAILIMAP_CONTINUE_REQ_TEXT: + mailimap_resp_text_free(cont_req->cr_data.cr_text); + break; + case MAILIMAP_CONTINUE_REQ_BASE64: + mailimap_base64_free(cont_req->cr_data.cr_base64); + break; + } + free(cont_req); +} + +struct mailimap_date_time * +mailimap_date_time_new(int dt_day, int dt_month, int dt_year, int dt_hour, + int dt_min, int dt_sec, int dt_zone) +{ + struct mailimap_date_time * date_time; + + date_time = malloc(sizeof(* date_time)); + if (date_time == NULL) + return NULL; + + date_time->dt_day = dt_day; + date_time->dt_month = dt_month; + date_time->dt_year = dt_year; + date_time->dt_hour = dt_hour; + date_time->dt_min = dt_min; + date_time->dt_day = dt_sec; + date_time->dt_zone = dt_zone; + + return date_time; +} + +void mailimap_date_time_free(struct mailimap_date_time * date_time) +{ + free(date_time); +} + + + +struct mailimap_envelope * +mailimap_envelope_new(char * env_date, char * env_subject, + struct mailimap_env_from * env_from, + struct mailimap_env_sender * env_sender, + struct mailimap_env_reply_to * env_reply_to, + struct mailimap_env_to * env_to, + struct mailimap_env_cc* env_cc, + struct mailimap_env_bcc * env_bcc, + char * env_in_reply_to, char * env_message_id) +{ + struct mailimap_envelope * env; + + env = malloc(sizeof(* env)); + if (env == NULL) + return NULL; + + env->env_date = env_date; + env->env_subject = env_subject; + env->env_from = env_from; + env->env_sender = env_sender; + env->env_reply_to = env_reply_to; + env->env_to = env_to; + env->env_cc = env_cc; + env->env_bcc = env_bcc; + env->env_in_reply_to = env_in_reply_to; + env->env_message_id = env_message_id; + + return env; +} + + +void mailimap_envelope_free(struct mailimap_envelope * env) +{ + if (env->env_date) + mailimap_env_date_free(env->env_date); + if (env->env_subject) + mailimap_env_subject_free(env->env_subject); + if (env->env_from) + mailimap_env_from_free(env->env_from); + if (env->env_sender) + mailimap_env_sender_free(env->env_sender); + if (env->env_reply_to) + mailimap_env_reply_to_free(env->env_reply_to); + if (env->env_to) + mailimap_env_to_free(env->env_to); + if (env->env_cc) + mailimap_env_cc_free(env->env_cc); + if (env->env_bcc) + mailimap_env_bcc_free(env->env_bcc); + if (env->env_in_reply_to) + mailimap_env_in_reply_to_free(env->env_in_reply_to); + if (env->env_message_id) + mailimap_env_message_id_free(env->env_message_id); + + free(env); +} + + +static void mailimap_address_list_free(clist * addr_list) +{ + if (addr_list != NULL) { + clist_foreach(addr_list, (clist_func) mailimap_address_free, NULL); + clist_free(addr_list); + } +} + + +struct mailimap_env_bcc * mailimap_env_bcc_new(clist * bcc_list) +{ + struct mailimap_env_bcc * env_bcc; + + env_bcc = malloc(sizeof(* env_bcc)); + if (env_bcc == NULL) + return NULL; + env_bcc->bcc_list = bcc_list; + + return env_bcc; +} + +void mailimap_env_bcc_free(struct mailimap_env_bcc * env_bcc) +{ + mailimap_address_list_free(env_bcc->bcc_list); + free(env_bcc); +} + + +struct mailimap_env_cc * mailimap_env_cc_new(clist * cc_list) +{ + struct mailimap_env_cc * env_cc; + + env_cc = malloc(sizeof(* env_cc)); + if (env_cc == NULL) + return NULL; + env_cc->cc_list = cc_list; + + return env_cc; +} + +void mailimap_env_cc_free(struct mailimap_env_cc * env_cc) +{ + mailimap_address_list_free(env_cc->cc_list); + free(env_cc); +} + + +void mailimap_env_date_free(char * date) +{ + mailimap_nstring_free(date); +} + + +struct mailimap_env_from * mailimap_env_from_new(clist * frm_list) +{ + struct mailimap_env_from * env_from; + + env_from = malloc(sizeof(* env_from)); + if (env_from == NULL) + return NULL; + env_from->frm_list = frm_list; + + return env_from; +} + +void mailimap_env_from_free(struct mailimap_env_from * env_from) +{ + mailimap_address_list_free(env_from->frm_list); + free(env_from); +} + + +void mailimap_env_in_reply_to_free(char * in_reply_to) +{ + mailimap_nstring_free(in_reply_to); +} + +void mailimap_env_message_id_free(char * message_id) +{ + mailimap_nstring_free(message_id); +} + +struct mailimap_env_reply_to * mailimap_env_reply_to_new(clist * rt_list) +{ + struct mailimap_env_reply_to * env_reply_to; + + env_reply_to = malloc(sizeof(* env_reply_to)); + if (env_reply_to == NULL) + return NULL; + env_reply_to->rt_list = rt_list; + + return env_reply_to; +} + +void +mailimap_env_reply_to_free(struct mailimap_env_reply_to * env_reply_to) +{ + mailimap_address_list_free(env_reply_to->rt_list); + free(env_reply_to); +} + +struct mailimap_env_sender * mailimap_env_sender_new(clist * snd_list) +{ + struct mailimap_env_sender * env_sender; + + env_sender = malloc(sizeof(* env_sender)); + if (env_sender == NULL) + return NULL; + env_sender->snd_list = snd_list; + + return env_sender; +} + +void mailimap_env_sender_free(struct mailimap_env_sender * env_sender) +{ + mailimap_address_list_free(env_sender->snd_list); + free(env_sender); +} + +void mailimap_env_subject_free(char * subject) +{ + mailimap_nstring_free(subject); +} + +struct mailimap_env_to * mailimap_env_to_new(clist * to_list) +{ + struct mailimap_env_to * env_to; + + env_to = malloc(sizeof(* env_to)); + if (env_to == NULL) + return NULL; + env_to->to_list = to_list; + + return env_to; +} + +void mailimap_env_to_free(struct mailimap_env_to * env_to) +{ + mailimap_address_list_free(env_to->to_list); + free(env_to); +} + + + +struct mailimap_flag * mailimap_flag_new(int fl_type, + char * fl_keyword, char * fl_extension) +{ + struct mailimap_flag * f; + + f = malloc(sizeof(* f)); + if (f == NULL) + return NULL; + f->fl_type = fl_type; + switch (fl_type) { + case MAILIMAP_FLAG_KEYWORD: + f->fl_data.fl_keyword = fl_keyword; + break; + case MAILIMAP_FLAG_EXTENSION: + f->fl_data.fl_extension = fl_extension; + break; + } + + return f; +} + +void mailimap_flag_free(struct mailimap_flag * f) +{ + switch (f->fl_type) { + case MAILIMAP_FLAG_KEYWORD: + mailimap_flag_keyword_free(f->fl_data.fl_keyword); + break; + case MAILIMAP_FLAG_EXTENSION: + mailimap_flag_extension_free(f->fl_data.fl_extension); + break; + } + free(f); +} + + + +void mailimap_flag_extension_free(char * flag_extension) +{ + mailimap_atom_free(flag_extension); +} + + + +struct mailimap_flag_fetch * +mailimap_flag_fetch_new(int fl_type, struct mailimap_flag * fl_flag) +{ + struct mailimap_flag_fetch * flag_fetch; + + flag_fetch = malloc(sizeof(* flag_fetch)); + if (flag_fetch == NULL) + return NULL; + + flag_fetch->fl_type = fl_type; + flag_fetch->fl_flag = fl_flag; + + return flag_fetch; +} + +void mailimap_flag_fetch_free(struct mailimap_flag_fetch * flag_fetch) +{ + if (flag_fetch->fl_flag) + mailimap_flag_free(flag_fetch->fl_flag); + free(flag_fetch); +} + + + +void mailimap_flag_keyword_free(char * flag_keyword) +{ + mailimap_atom_free(flag_keyword); +} + + + + +struct mailimap_flag_list * +mailimap_flag_list_new(clist * fl_list) +{ + struct mailimap_flag_list * flag_list; + + flag_list = malloc(sizeof(* flag_list)); + if (flag_list == NULL) + return NULL; + flag_list->fl_list = fl_list; + + return flag_list; +} + +void mailimap_flag_list_free(struct mailimap_flag_list * flag_list) +{ + clist_foreach(flag_list->fl_list, (clist_func) mailimap_flag_free, NULL); + clist_free(flag_list->fl_list); + free(flag_list); +} + + + + + +struct mailimap_flag_perm * +mailimap_flag_perm_new(int fl_type, struct mailimap_flag * fl_flag) +{ + struct mailimap_flag_perm * flag_perm; + + flag_perm = malloc(sizeof(* flag_perm)); + if (flag_perm == NULL) + return NULL; + + flag_perm->fl_type = fl_type; + flag_perm->fl_flag = fl_flag; + + return flag_perm; +} + +void mailimap_flag_perm_free(struct mailimap_flag_perm * flag_perm) +{ + if (flag_perm->fl_flag != NULL) + mailimap_flag_free(flag_perm->fl_flag); + free(flag_perm); +} + + + + +struct mailimap_greeting * +mailimap_greeting_new(int gr_type, + struct mailimap_resp_cond_auth * gr_auth, + struct mailimap_resp_cond_bye * gr_bye) +{ + struct mailimap_greeting * greeting; + + greeting = malloc(sizeof(* greeting)); + if (greeting == NULL) + return NULL; + greeting->gr_type = gr_type; + switch (gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + greeting->gr_data.gr_auth = gr_auth; + break; + case MAILIMAP_GREETING_RESP_COND_BYE: + greeting->gr_data.gr_bye = gr_bye; + break; + } + + return greeting; +} + +void mailimap_greeting_free(struct mailimap_greeting * greeting) +{ + switch (greeting->gr_type) { + case MAILIMAP_GREETING_RESP_COND_AUTH: + mailimap_resp_cond_auth_free(greeting->gr_data.gr_auth); + break; + case MAILIMAP_GREETING_RESP_COND_BYE: + mailimap_resp_cond_bye_free(greeting->gr_data.gr_bye); + break; + } + free(greeting); +} + + + +void +mailimap_header_fld_name_free(char * header_fld_name) +{ + mailimap_astring_free(header_fld_name); +} + + + +struct mailimap_header_list * +mailimap_header_list_new(clist * hdr_list) +{ + struct mailimap_header_list * header_list; + + header_list = malloc(sizeof(* header_list)); + if (header_list == NULL) + return NULL; + + header_list->hdr_list = hdr_list; + + return header_list; +} + +void +mailimap_header_list_free(struct mailimap_header_list * header_list) +{ + clist_foreach(header_list->hdr_list, + (clist_func) mailimap_header_fld_name_free, + NULL); + clist_free(header_list->hdr_list); + free(header_list); +} + + + +void mailimap_literal_free(char * literal) +{ + /* free(literal); */ + mmap_string_unref(literal); +} + +void mailimap_mailbox_free(char * mb) +{ + mailimap_astring_free(mb); +} + + + + +struct mailimap_status_info * +mailimap_status_info_new(int st_att, uint32_t st_value) +{ + struct mailimap_status_info * info; + + info = malloc(sizeof(* info)); + if (info == NULL) + return NULL; + info->st_att = st_att; + info->st_value = st_value; + + return info; +} + +void mailimap_status_info_free(struct mailimap_status_info * info) +{ + free(info); +} + + + +struct mailimap_mailbox_data_status * +mailimap_mailbox_data_status_new(char * st_mailbox, + clist * st_info_list) +{ + struct mailimap_mailbox_data_status * mb_data_status; + + mb_data_status = malloc(sizeof(* mb_data_status)); + if (mb_data_status == NULL) + return NULL; + mb_data_status->st_mailbox = st_mailbox; + mb_data_status->st_info_list = st_info_list; + + return mb_data_status; +} + +void +mailimap_mailbox_data_search_free(clist * data_search) +{ + clist_foreach(data_search, (clist_func) mailimap_number_alloc_free, NULL); + clist_free(data_search); +} + +void +mailimap_mailbox_data_status_free(struct mailimap_mailbox_data_status * info) +{ + mailimap_mailbox_free(info->st_mailbox); + clist_foreach(info->st_info_list, (clist_func) mailimap_status_info_free, + NULL); + clist_free(info->st_info_list); + free(info); +} + + +static void +mailimap_mailbox_data_flags_free(struct mailimap_flag_list * flag_list) +{ + mailimap_flag_list_free(flag_list); +} + +static void +mailimap_mailbox_data_list_free(struct mailimap_mailbox_list * mb_list) +{ + mailimap_mailbox_list_free(mb_list); +} + +static void +mailimap_mailbox_data_lsub_free(struct mailimap_mailbox_list * mb_lsub) +{ + mailimap_mailbox_list_free(mb_lsub); +} + + + + + + +struct mailimap_mailbox_data * +mailimap_mailbox_data_new(int mbd_type, struct mailimap_flag_list * mbd_flags, + struct mailimap_mailbox_list * mbd_list, + struct mailimap_mailbox_list * mbd_lsub, + clist * mbd_search, + struct mailimap_mailbox_data_status * mbd_status, + uint32_t mbd_exists, + uint32_t mbd_recent, + struct mailimap_extension_data * mbd_extension) +{ + struct mailimap_mailbox_data * data; + + data = malloc(sizeof(* data)); + if (data == NULL) + return NULL; + + data->mbd_type = mbd_type; + switch (mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + data->mbd_data.mbd_flags = mbd_flags; + break; + case MAILIMAP_MAILBOX_DATA_LIST: + data->mbd_data.mbd_list = mbd_list; + break; + case MAILIMAP_MAILBOX_DATA_LSUB: + data->mbd_data.mbd_lsub = mbd_lsub; + break; + case MAILIMAP_MAILBOX_DATA_SEARCH: + data->mbd_data.mbd_search = mbd_search; + break; + case MAILIMAP_MAILBOX_DATA_STATUS: + data->mbd_data.mbd_status = mbd_status; + break; + case MAILIMAP_MAILBOX_DATA_EXISTS: + data->mbd_data.mbd_exists = mbd_exists; + break; + case MAILIMAP_MAILBOX_DATA_RECENT: + data->mbd_data.mbd_recent = mbd_recent; + break; + case MAILIMAP_MAILBOX_DATA_EXTENSION_DATA: + data->mbd_data.mbd_extension = mbd_extension; + break; + } + + return data; +} + +void +mailimap_mailbox_data_free(struct mailimap_mailbox_data * mb_data) +{ + switch (mb_data->mbd_type) { + case MAILIMAP_MAILBOX_DATA_FLAGS: + if (mb_data->mbd_data.mbd_flags != NULL) + mailimap_mailbox_data_flags_free(mb_data->mbd_data.mbd_flags); + break; + case MAILIMAP_MAILBOX_DATA_LIST: + if (mb_data->mbd_data.mbd_list != NULL) + mailimap_mailbox_data_list_free(mb_data->mbd_data.mbd_list); + break; + case MAILIMAP_MAILBOX_DATA_LSUB: + if (mb_data->mbd_data.mbd_lsub != NULL) + mailimap_mailbox_data_lsub_free(mb_data->mbd_data.mbd_lsub); + break; + case MAILIMAP_MAILBOX_DATA_SEARCH: + if (mb_data->mbd_data.mbd_search != NULL) + mailimap_mailbox_data_search_free(mb_data->mbd_data.mbd_search); + break; + case MAILIMAP_MAILBOX_DATA_STATUS: + if (mb_data->mbd_data.mbd_status != NULL) + mailimap_mailbox_data_status_free(mb_data->mbd_data.mbd_status); + break; + case MAILIMAP_MAILBOX_DATA_EXTENSION_DATA: + if (mb_data->mbd_data.mbd_extension != NULL) + mailimap_extension_data_free(mb_data->mbd_data.mbd_extension); + break; + } + free(mb_data); +} + + + + + +struct mailimap_mbx_list_flags * +mailimap_mbx_list_flags_new(int mbf_type, clist * mbf_oflags, + int mbf_sflag) +{ + struct mailimap_mbx_list_flags * mbx_list_flags; + + mbx_list_flags = malloc(sizeof(* mbx_list_flags)); + if (mbx_list_flags == NULL) + return NULL; + + mbx_list_flags->mbf_type = mbf_type; + mbx_list_flags->mbf_oflags = mbf_oflags; + mbx_list_flags->mbf_sflag = mbf_sflag; + + return mbx_list_flags; +} + +void +mailimap_mbx_list_flags_free(struct mailimap_mbx_list_flags * mbx_list_flags) +{ + clist_foreach(mbx_list_flags->mbf_oflags, + (clist_func) mailimap_mbx_list_oflag_free, + NULL); + clist_free(mbx_list_flags->mbf_oflags); + + free(mbx_list_flags); +} + + +struct mailimap_mbx_list_oflag * +mailimap_mbx_list_oflag_new(int of_type, char * of_flag_ext) +{ + struct mailimap_mbx_list_oflag * oflag; + + oflag = malloc(sizeof(* oflag)); + if (oflag == NULL) + return NULL; + + oflag->of_type = of_type; + oflag->of_flag_ext = of_flag_ext; + + return oflag; +} + +void +mailimap_mbx_list_oflag_free(struct mailimap_mbx_list_oflag * oflag) +{ + if (oflag->of_flag_ext != NULL) + mailimap_flag_extension_free(oflag->of_flag_ext); + free(oflag); +} + + + +struct mailimap_mailbox_list * +mailimap_mailbox_list_new(struct mailimap_mbx_list_flags * mbx_flags, + char mb_delimiter, char * mb_name) +{ + struct mailimap_mailbox_list * mb_list; + + mb_list = malloc(sizeof(* mb_list)); + if (mb_list == NULL) + return NULL; + + mb_list->mb_flag = mbx_flags; + mb_list->mb_delimiter = mb_delimiter; + mb_list->mb_name = mb_name; + + return mb_list; +} + +void +mailimap_mailbox_list_free(struct mailimap_mailbox_list * mb_list) +{ + if (mb_list->mb_flag != NULL) + mailimap_mbx_list_flags_free(mb_list->mb_flag); + if (mb_list->mb_name != NULL) + mailimap_mailbox_free(mb_list->mb_name); + free(mb_list); +} + + + +struct mailimap_media_basic * +mailimap_media_basic_new(int med_type, + char * med_basic_type, char * med_subtype) +{ + struct mailimap_media_basic * media_basic; + + media_basic = malloc(sizeof(* media_basic)); + if (media_basic == NULL) + return NULL; + media_basic->med_type = med_type; + media_basic->med_basic_type = med_basic_type; + media_basic->med_subtype = med_subtype; + + return media_basic; +} + +void +mailimap_media_basic_free(struct mailimap_media_basic * media_basic) +{ + mailimap_string_free(media_basic->med_basic_type); + mailimap_media_subtype_free(media_basic->med_subtype); + free(media_basic); +} + + + +void mailimap_media_subtype_free(char * media_subtype) +{ + mmap_string_unref(media_subtype); +} + + +void mailimap_media_text_free(char * media_text) +{ + mailimap_media_subtype_free(media_text); +} + + + +struct mailimap_message_data * +mailimap_message_data_new(uint32_t mdt_number, int mdt_type, + struct mailimap_msg_att * mdt_msg_att) +{ + struct mailimap_message_data * msg_data; + + msg_data = malloc(sizeof(* msg_data)); + if (msg_data == NULL) + free(msg_data); + + msg_data->mdt_number = mdt_number; + msg_data->mdt_type = mdt_type; + msg_data->mdt_msg_att = mdt_msg_att; + + return msg_data; +} + +void +mailimap_message_data_free(struct mailimap_message_data * msg_data) +{ + if (msg_data->mdt_msg_att != NULL) + mailimap_msg_att_free(msg_data->mdt_msg_att); + free(msg_data); +} + + + + +struct mailimap_msg_att_item * +mailimap_msg_att_item_new(int att_type, + struct mailimap_msg_att_dynamic * att_dyn, + struct mailimap_msg_att_static * att_static) +{ + struct mailimap_msg_att_item * item; + + item = malloc(sizeof(* item)); + if (item == NULL) + return item; + + item->att_type = att_type; + switch (att_type) { + case MAILIMAP_MSG_ATT_ITEM_DYNAMIC: + item->att_data.att_dyn = att_dyn; + break; + case MAILIMAP_MSG_ATT_ITEM_STATIC: + item->att_data.att_static = att_static; + break; + } + + return item; +} + +void +mailimap_msg_att_item_free(struct mailimap_msg_att_item * item) +{ + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ITEM_DYNAMIC: + mailimap_msg_att_dynamic_free(item->att_data.att_dyn); + break; + case MAILIMAP_MSG_ATT_ITEM_STATIC: + mailimap_msg_att_static_free(item->att_data.att_static); + break; + } + free(item); +} + + +struct mailimap_msg_att * +mailimap_msg_att_new(clist * att_list) +{ + struct mailimap_msg_att * msg_att; + + msg_att = malloc(sizeof(* msg_att)); + if (msg_att == NULL) + return NULL; + + msg_att->att_list = att_list; + msg_att->att_number = 0; + + return msg_att; +} + +void mailimap_msg_att_free(struct mailimap_msg_att * msg_att) +{ + clist_foreach(msg_att->att_list, + (clist_func) mailimap_msg_att_item_free, NULL); + clist_free(msg_att->att_list); + free(msg_att); +} + + + +struct mailimap_msg_att_dynamic * +mailimap_msg_att_dynamic_new(clist * att_list) +{ + struct mailimap_msg_att_dynamic * msg_att_dyn; + + msg_att_dyn = malloc(sizeof(* msg_att_dyn)); + if (msg_att_dyn == NULL) + return NULL; + + msg_att_dyn->att_list = att_list; + + return msg_att_dyn; +} + +void +mailimap_msg_att_dynamic_free(struct mailimap_msg_att_dynamic * msg_att_dyn) +{ + if (msg_att_dyn->att_list != NULL) { + clist_foreach(msg_att_dyn->att_list, + (clist_func) mailimap_flag_fetch_free, + NULL); + clist_free(msg_att_dyn->att_list); + } + free(msg_att_dyn); +} + + +struct mailimap_msg_att_body_section * +mailimap_msg_att_body_section_new(struct mailimap_section * sec_section, + uint32_t sec_origin_octet, + char * sec_body_part, + size_t sec_length) +{ + struct mailimap_msg_att_body_section * msg_att_body_section; + + msg_att_body_section = malloc(sizeof(* msg_att_body_section)); + if (msg_att_body_section == NULL) + return NULL; + + msg_att_body_section->sec_section = sec_section; + msg_att_body_section->sec_origin_octet = sec_origin_octet; + msg_att_body_section->sec_body_part = sec_body_part; + msg_att_body_section->sec_length = sec_length; + + return msg_att_body_section; +} + +void +mailimap_msg_att_body_section_free(struct mailimap_msg_att_body_section * + msg_att_body_section) +{ + if (msg_att_body_section->sec_section != NULL) + mailimap_section_free(msg_att_body_section->sec_section); + if (msg_att_body_section->sec_body_part != NULL) + mailimap_nstring_free(msg_att_body_section->sec_body_part); + free(msg_att_body_section); +} + + + + + + +void mailimap_msg_att_envelope_free(struct mailimap_envelope * env) +{ + mailimap_envelope_free(env); +} + +void +mailimap_msg_att_internaldate_free(struct mailimap_date_time * date_time) +{ + mailimap_date_time_free(date_time); +} + +void +mailimap_msg_att_rfc822_free(char * str) +{ + mailimap_nstring_free(str); +} + + +void +mailimap_msg_att_rfc822_header_free(char * str) +{ + mailimap_nstring_free(str); +} + +void +mailimap_msg_att_rfc822_text_free(char * str) +{ + mailimap_nstring_free(str); +} + +void +mailimap_msg_att_body_free(struct mailimap_body * body) +{ + mailimap_body_free(body); +} + +void +mailimap_msg_att_bodystructure_free(struct mailimap_body * body) +{ + mailimap_body_free(body); +} + + + +struct mailimap_msg_att_static * +mailimap_msg_att_static_new(int att_type, struct mailimap_envelope * att_env, + struct mailimap_date_time * att_internal_date, + char * att_rfc822, + char * att_rfc822_header, + char * att_rfc822_text, + size_t att_length, + uint32_t att_rfc822_size, + struct mailimap_body * att_bodystructure, + struct mailimap_body * att_body, + struct mailimap_msg_att_body_section * att_body_section, + uint32_t att_uid) +{ + struct mailimap_msg_att_static * item; + + item = malloc(sizeof(* item)); + if (item == NULL) + return FALSE; + + item->att_type = att_type; + switch (att_type) { + case MAILIMAP_MSG_ATT_ENVELOPE: + item->att_data.att_env = att_env; + break; + case MAILIMAP_MSG_ATT_INTERNALDATE: + item->att_data.att_internal_date = att_internal_date; + break; + case MAILIMAP_MSG_ATT_RFC822: + item->att_data.att_rfc822.att_content = att_rfc822; + item->att_data.att_rfc822.att_length = att_length; + break; + case MAILIMAP_MSG_ATT_RFC822_HEADER: + item->att_data.att_rfc822_header.att_content = att_rfc822_header; + item->att_data.att_rfc822_header.att_length = att_length; + break; + case MAILIMAP_MSG_ATT_RFC822_TEXT: + item->att_data.att_rfc822_text.att_content = att_rfc822_text; + item->att_data.att_rfc822_text.att_length = att_length; + break; + case MAILIMAP_MSG_ATT_RFC822_SIZE: + item->att_data.att_rfc822_size = att_rfc822_size; + break; + case MAILIMAP_MSG_ATT_BODY: + item->att_data.att_body = att_body; + break; + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + item->att_data.att_bodystructure = att_bodystructure; + break; + case MAILIMAP_MSG_ATT_BODY_SECTION: + item->att_data.att_body_section = att_body_section; + break; + case MAILIMAP_MSG_ATT_UID: + item->att_data.att_uid = att_uid; + break; + } + + return item; +} + +void +mailimap_msg_att_static_free(struct mailimap_msg_att_static * item) +{ + switch (item->att_type) { + case MAILIMAP_MSG_ATT_ENVELOPE: + if (item->att_data.att_env != NULL) + mailimap_msg_att_envelope_free(item->att_data.att_env); + break; + case MAILIMAP_MSG_ATT_INTERNALDATE: + if (item->att_data.att_internal_date != NULL) + mailimap_msg_att_internaldate_free(item->att_data.att_internal_date); + break; + case MAILIMAP_MSG_ATT_RFC822: + if (item->att_data.att_rfc822.att_content != NULL) + mailimap_msg_att_rfc822_free(item->att_data.att_rfc822.att_content); + break; + case MAILIMAP_MSG_ATT_RFC822_HEADER: + if (item->att_data.att_rfc822_header.att_content != NULL) + mailimap_msg_att_rfc822_header_free(item->att_data.att_rfc822_header.att_content); + break; + case MAILIMAP_MSG_ATT_RFC822_TEXT: + if (item->att_data.att_rfc822_text.att_content != NULL) + mailimap_msg_att_rfc822_text_free(item->att_data.att_rfc822_text.att_content); + break; + case MAILIMAP_MSG_ATT_BODYSTRUCTURE: + if (item->att_data.att_bodystructure != NULL) + mailimap_msg_att_bodystructure_free(item->att_data.att_bodystructure); + break; + case MAILIMAP_MSG_ATT_BODY: + if (item->att_data.att_body != NULL) + mailimap_msg_att_body_free(item->att_data.att_body); + break; + case MAILIMAP_MSG_ATT_BODY_SECTION: + if (item->att_data.att_body_section != NULL) + mailimap_msg_att_body_section_free(item->att_data.att_body_section); + break; + } + free(item); +} + + + + +void mailimap_nstring_free(char * str) +{ + if (str != NULL) + mailimap_string_free(str); +} + + + + + + + +struct mailimap_cont_req_or_resp_data * +mailimap_cont_req_or_resp_data_new(int rsp_type, + struct mailimap_continue_req * rsp_cont_req, + struct mailimap_response_data * rsp_resp_data) +{ + struct mailimap_cont_req_or_resp_data * cont_req_or_resp_data; + + cont_req_or_resp_data = malloc(sizeof(* cont_req_or_resp_data)); + if (cont_req_or_resp_data == NULL) + return NULL; + + cont_req_or_resp_data->rsp_type = rsp_type; + switch (rsp_type) { + case MAILIMAP_RESP_CONT_REQ: + cont_req_or_resp_data->rsp_data.rsp_cont_req = rsp_cont_req; + break; + case MAILIMAP_RESP_RESP_DATA: + cont_req_or_resp_data->rsp_data.rsp_resp_data = rsp_resp_data; + break; + } + + return cont_req_or_resp_data; +} + +void +mailimap_cont_req_or_resp_data_free(struct mailimap_cont_req_or_resp_data * + cont_req_or_resp_data) +{ + switch (cont_req_or_resp_data->rsp_type) { + case MAILIMAP_RESP_CONT_REQ: + if (cont_req_or_resp_data->rsp_data.rsp_cont_req != NULL) + mailimap_continue_req_free(cont_req_or_resp_data->rsp_data.rsp_cont_req); + break; + case MAILIMAP_RESP_RESP_DATA: + if (cont_req_or_resp_data->rsp_data.rsp_resp_data != NULL) + mailimap_response_data_free(cont_req_or_resp_data->rsp_data.rsp_resp_data); + break; + } + free(cont_req_or_resp_data); +} + + + + +struct mailimap_response * +mailimap_response_new(clist * rsp_cont_req_or_resp_data_list, + struct mailimap_response_done * rsp_resp_done) +{ + struct mailimap_response * resp; + + resp = malloc(sizeof(* resp)); + if (resp == NULL) + return NULL; + + resp->rsp_cont_req_or_resp_data_list = rsp_cont_req_or_resp_data_list; + resp->rsp_resp_done = rsp_resp_done; + + return resp; +} + +void +mailimap_response_free(struct mailimap_response * resp) +{ + if (resp->rsp_cont_req_or_resp_data_list != NULL) { + clist_foreach(resp->rsp_cont_req_or_resp_data_list, + (clist_func) mailimap_cont_req_or_resp_data_free, NULL); + clist_free(resp->rsp_cont_req_or_resp_data_list); + } + mailimap_response_done_free(resp->rsp_resp_done); + free(resp); +} + + + +struct mailimap_response_data * +mailimap_response_data_new(int rsp_type, + struct mailimap_resp_cond_state * rsp_cond_state, + struct mailimap_resp_cond_bye * rsp_bye, + struct mailimap_mailbox_data * rsp_mailbox_data, + struct mailimap_message_data * rsp_message_data, + struct mailimap_capability_data * rsp_capability_data, + struct mailimap_extension_data * rsp_extension_data) +{ + struct mailimap_response_data * resp_data; + + resp_data = malloc(sizeof(* resp_data)); + if (resp_data == NULL) + return NULL; + resp_data->rsp_type = rsp_type; + + switch (rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + resp_data->rsp_data.rsp_cond_state = rsp_cond_state; + break; + case MAILIMAP_RESP_DATA_TYPE_COND_BYE: + resp_data->rsp_data.rsp_bye = rsp_bye; + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + resp_data->rsp_data.rsp_mailbox_data = rsp_mailbox_data; + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + resp_data->rsp_data.rsp_message_data = rsp_message_data; + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + resp_data->rsp_data.rsp_capability_data = rsp_capability_data; + break; + case MAILIMAP_RESP_DATA_TYPE_EXTENSION_DATA: + resp_data->rsp_data.rsp_extension_data = rsp_extension_data; + break; + } + + return resp_data; +} + +void +mailimap_response_data_free(struct mailimap_response_data * resp_data) +{ + switch (resp_data->rsp_type) { + case MAILIMAP_RESP_DATA_TYPE_COND_STATE: + if (resp_data->rsp_data.rsp_cond_state != NULL) + mailimap_resp_cond_state_free(resp_data->rsp_data.rsp_cond_state); + break; + case MAILIMAP_RESP_DATA_TYPE_COND_BYE: + if (resp_data->rsp_data.rsp_bye != NULL) + mailimap_resp_cond_bye_free(resp_data->rsp_data.rsp_bye); + break; + case MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA: + if (resp_data->rsp_data.rsp_mailbox_data != NULL) + mailimap_mailbox_data_free(resp_data->rsp_data.rsp_mailbox_data); + break; + case MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA: + if (resp_data->rsp_data.rsp_message_data != NULL) + mailimap_message_data_free(resp_data->rsp_data.rsp_message_data); + break; + case MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA: + if (resp_data->rsp_data.rsp_capability_data != NULL) + mailimap_capability_data_free(resp_data->rsp_data.rsp_capability_data); + break; + case MAILIMAP_RESP_DATA_TYPE_EXTENSION_DATA: + if (resp_data->rsp_data.rsp_extension_data != NULL) + mailimap_extension_data_free(resp_data->rsp_data.rsp_extension_data); + break; + } + free(resp_data); +} + + + +struct mailimap_response_done * +mailimap_response_done_new(int rsp_type, + struct mailimap_response_tagged * rsp_tagged, + struct mailimap_response_fatal * rsp_fatal) +{ + struct mailimap_response_done * resp_done; + + resp_done = malloc(sizeof(* resp_done)); + if (resp_done == NULL) + return NULL; + + resp_done->rsp_type = rsp_type; + switch (rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + resp_done->rsp_data.rsp_tagged = rsp_tagged; + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + resp_done->rsp_data.rsp_fatal = rsp_fatal; + break; + } + + return resp_done; +} + +void mailimap_response_done_free(struct mailimap_response_done * + resp_done) +{ + switch (resp_done->rsp_type) { + case MAILIMAP_RESP_DONE_TYPE_TAGGED: + mailimap_response_tagged_free(resp_done->rsp_data.rsp_tagged); + break; + case MAILIMAP_RESP_DONE_TYPE_FATAL: + mailimap_response_fatal_free(resp_done->rsp_data.rsp_fatal); + break; + } + free(resp_done); +} + +struct mailimap_response_fatal * +mailimap_response_fatal_new(struct mailimap_resp_cond_bye * rsp_bye) +{ + struct mailimap_response_fatal * resp_fatal; + + resp_fatal = malloc(sizeof(* resp_fatal)); + if (resp_fatal == NULL) + return NULL; + + resp_fatal->rsp_bye = rsp_bye; + + return NULL; +} + +void mailimap_response_fatal_free(struct mailimap_response_fatal * resp_fatal) +{ + mailimap_resp_cond_bye_free(resp_fatal->rsp_bye); + free(resp_fatal); +} + +struct mailimap_response_tagged * +mailimap_response_tagged_new(char * rsp_tag, + struct mailimap_resp_cond_state * rsp_cond_state) +{ + struct mailimap_response_tagged * resp_tagged; + + resp_tagged = malloc(sizeof(* resp_tagged)); + if (resp_tagged == NULL) + return NULL; + + resp_tagged->rsp_tag = rsp_tag; + resp_tagged->rsp_cond_state = rsp_cond_state; + + return resp_tagged; +} + +void +mailimap_response_tagged_free(struct mailimap_response_tagged * tagged) +{ + mailimap_tag_free(tagged->rsp_tag); + mailimap_resp_cond_state_free(tagged->rsp_cond_state); + free(tagged); +} + + + +struct mailimap_resp_cond_auth * +mailimap_resp_cond_auth_new(int rsp_type, + struct mailimap_resp_text * rsp_text) +{ + struct mailimap_resp_cond_auth * cond_auth; + + cond_auth = malloc(sizeof(* cond_auth)); + if (cond_auth == NULL) + return NULL; + + cond_auth->rsp_type = rsp_type; + cond_auth->rsp_text = rsp_text; + + return cond_auth; +} + +void +mailimap_resp_cond_auth_free(struct mailimap_resp_cond_auth * cond_auth) +{ + mailimap_resp_text_free(cond_auth->rsp_text); + free(cond_auth); +} + + + +struct mailimap_resp_cond_bye * +mailimap_resp_cond_bye_new(struct mailimap_resp_text * rsp_text) +{ + struct mailimap_resp_cond_bye * cond_bye; + + cond_bye = malloc(sizeof(* cond_bye)); + if (cond_bye == NULL) + return NULL; + + cond_bye->rsp_text = rsp_text; + + return cond_bye; +} + + +void +mailimap_resp_cond_bye_free(struct mailimap_resp_cond_bye * cond_bye) +{ + mailimap_resp_text_free(cond_bye->rsp_text); + free(cond_bye); +} + + +struct mailimap_resp_cond_state * +mailimap_resp_cond_state_new(int rsp_type, + struct mailimap_resp_text * rsp_text) +{ + struct mailimap_resp_cond_state * cond_state; + + cond_state = malloc(sizeof(* cond_state)); + if (cond_state == NULL) + return NULL; + + cond_state->rsp_type = rsp_type; + cond_state->rsp_text = rsp_text; + + return cond_state; +} + +void +mailimap_resp_cond_state_free(struct mailimap_resp_cond_state * cond_state) +{ + mailimap_resp_text_free(cond_state->rsp_text); + free(cond_state); +} + + +struct mailimap_resp_text * +mailimap_resp_text_new(struct mailimap_resp_text_code * rsp_code, + char * rsp_text) +{ + struct mailimap_resp_text * resp_text; + + resp_text = malloc(sizeof(* resp_text)); + if (resp_text == NULL) + return NULL; + + resp_text->rsp_code = rsp_code; + resp_text->rsp_text = rsp_text; + + return resp_text; +} + +void mailimap_resp_text_free(struct mailimap_resp_text * resp_text) +{ + if (resp_text->rsp_code) + mailimap_resp_text_code_free(resp_text->rsp_code); + if (resp_text->rsp_text) + mailimap_text_free(resp_text->rsp_text); + free(resp_text); +} + + + + +struct mailimap_resp_text_code * +mailimap_resp_text_code_new(int rc_type, clist * rc_badcharset, + struct mailimap_capability_data * rc_cap_data, + clist * rc_perm_flags, + uint32_t rc_uidnext, uint32_t rc_uidvalidity, + uint32_t rc_first_unseen, char * rc_atom, char * rc_atom_value, + struct mailimap_extension_data * rc_ext_data) +{ + struct mailimap_resp_text_code * resp_text_code; + + resp_text_code = malloc(sizeof(* resp_text_code)); + if (resp_text_code == NULL) + return NULL; + + resp_text_code->rc_type = rc_type; + switch (rc_type) { + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + resp_text_code->rc_data.rc_badcharset = rc_badcharset; + break; + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + resp_text_code->rc_data.rc_cap_data = rc_cap_data; + break; + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + resp_text_code->rc_data.rc_perm_flags = rc_perm_flags; + break; + case MAILIMAP_RESP_TEXT_CODE_UIDNEXT: + resp_text_code->rc_data.rc_uidnext = rc_uidnext; + break; + case MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY: + resp_text_code->rc_data.rc_uidvalidity = rc_uidvalidity; + break; + case MAILIMAP_RESP_TEXT_CODE_UNSEEN: + resp_text_code->rc_data.rc_first_unseen = rc_first_unseen; + break; + case MAILIMAP_RESP_TEXT_CODE_OTHER: + resp_text_code->rc_data.rc_atom.atom_name = rc_atom; + resp_text_code->rc_data.rc_atom.atom_value = rc_atom_value; + break; + case MAILIMAP_RESP_TEXT_CODE_EXTENSION: + resp_text_code->rc_data.rc_ext_data = rc_ext_data; + break; + } + + return resp_text_code; +} + +void +mailimap_resp_text_code_free(struct mailimap_resp_text_code * resp_text_code) +{ + switch (resp_text_code->rc_type) { + case MAILIMAP_RESP_TEXT_CODE_BADCHARSET: + if (resp_text_code->rc_data.rc_badcharset != NULL) { + clist_foreach(resp_text_code->rc_data.rc_badcharset, + (clist_func) mailimap_astring_free, + NULL); + clist_free(resp_text_code->rc_data.rc_badcharset); + } + break; + case MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA: + if (resp_text_code->rc_data.rc_cap_data != NULL) + mailimap_capability_data_free(resp_text_code->rc_data.rc_cap_data); + break; + case MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS: + if (resp_text_code->rc_data.rc_perm_flags != NULL) { + clist_foreach(resp_text_code->rc_data.rc_perm_flags, + (clist_func) mailimap_flag_perm_free, NULL); + clist_free(resp_text_code->rc_data.rc_perm_flags); + } + break; + case MAILIMAP_RESP_TEXT_CODE_OTHER: + if (resp_text_code->rc_data.rc_atom.atom_name != NULL) + mailimap_atom_free(resp_text_code->rc_data.rc_atom.atom_name); + if (resp_text_code->rc_data.rc_atom.atom_value != NULL) + mailimap_custom_string_free(resp_text_code->rc_data.rc_atom.atom_value); + break; + case MAILIMAP_RESP_TEXT_CODE_EXTENSION: + if (resp_text_code->rc_data.rc_ext_data != NULL) + mailimap_extension_data_free(resp_text_code->rc_data.rc_ext_data); + break; + } + free(resp_text_code); +} + + +struct mailimap_section * +mailimap_section_new(struct mailimap_section_spec * sec_spec) +{ + struct mailimap_section * section; + + section = malloc(sizeof(* section)); + if (section == NULL) + return NULL; + + section->sec_spec = sec_spec; + + return section; +} + +void mailimap_section_free(struct mailimap_section * section) +{ + if (section->sec_spec != NULL) + mailimap_section_spec_free(section->sec_spec); + free(section); +} + + + +struct mailimap_section_msgtext * +mailimap_section_msgtext_new(int sec_type, + struct mailimap_header_list * sec_header_list) +{ + struct mailimap_section_msgtext * msgtext; + + msgtext = malloc(sizeof(* msgtext)); + if (msgtext == NULL) + return FALSE; + + msgtext->sec_type = sec_type; + msgtext->sec_header_list = sec_header_list; + + return msgtext; +} + +void +mailimap_section_msgtext_free(struct mailimap_section_msgtext * msgtext) +{ + if (msgtext->sec_header_list != NULL) + mailimap_header_list_free(msgtext->sec_header_list); + free(msgtext); +} + + +struct mailimap_section_part * +mailimap_section_part_new(clist * sec_id) +{ + struct mailimap_section_part * section_part; + + section_part = malloc(sizeof(* section_part)); + if (section_part == NULL) + return NULL; + + section_part->sec_id = sec_id; + + return section_part; +} + +void +mailimap_section_part_free(struct mailimap_section_part * section_part) +{ + clist_foreach(section_part->sec_id, + (clist_func) mailimap_number_alloc_free, NULL); + clist_free(section_part->sec_id); + free(section_part); +} + + +struct mailimap_section_spec * +mailimap_section_spec_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext, + struct mailimap_section_part * sec_part, + struct mailimap_section_text * sec_text) +{ + struct mailimap_section_spec * section_spec; + + section_spec = malloc(sizeof(* section_spec)); + if (section_spec == NULL) + return NULL; + + section_spec->sec_type = sec_type; + switch (sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + section_spec->sec_data.sec_msgtext = sec_msgtext; + break; + case MAILIMAP_SECTION_SPEC_SECTION_PART: + section_spec->sec_data.sec_part = sec_part; + break; + } + section_spec->sec_text = sec_text; + + return section_spec; +} + +void +mailimap_section_spec_free(struct mailimap_section_spec * section_spec) +{ + if (section_spec->sec_text) + mailimap_section_text_free(section_spec->sec_text); + + switch (section_spec->sec_type) { + case MAILIMAP_SECTION_SPEC_SECTION_PART: + if (section_spec->sec_data.sec_part != NULL) + mailimap_section_part_free(section_spec->sec_data.sec_part); + break; + case MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT: + /* handle case where it can be detached */ + if (section_spec->sec_data.sec_msgtext != NULL) + mailimap_section_msgtext_free(section_spec->sec_data.sec_msgtext); + break; + } + free(section_spec); +} + + +struct mailimap_section_text * +mailimap_section_text_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext) +{ + struct mailimap_section_text * section_text; + + section_text = malloc(sizeof(* section_text)); + if (section_text == NULL) + return NULL; + + section_text->sec_type = sec_type; + section_text->sec_msgtext = sec_msgtext; + + return section_text; +} + +void +mailimap_section_text_free(struct mailimap_section_text * section_text) +{ + if (section_text->sec_msgtext != NULL) + mailimap_section_msgtext_free(section_text->sec_msgtext); + free(section_text); +} + + + + +void +mailimap_string_free(char * str) +{ + mmap_string_unref(str); +} + + + + + +void mailimap_tag_free(char * tag) +{ + mailimap_custom_string_free(tag); +} + + +void mailimap_text_free(char * text) +{ + mailimap_custom_string_free(text); +} + + + + + + + + + + + + + + + + + + + + + + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + + + + + + +/* sender only */ + + +/* COPY FETCH SEARCH STORE */ +/* set */ + +struct mailimap_set_item * +mailimap_set_item_new(uint32_t set_first, uint32_t set_last) +{ + struct mailimap_set_item * item; + + item = malloc(sizeof(* item)); + if (item == NULL) + return NULL; + + item->set_first = set_first; + item->set_last = set_last; + + return item; +} + +void mailimap_set_item_free(struct mailimap_set_item * set_item) +{ + free(set_item); +} + +struct mailimap_set * mailimap_set_new(clist * set_list) +{ + struct mailimap_set * set; + + set = malloc(sizeof(* set)); + if (set == NULL) + return NULL; + + set->set_list = set_list; + + return set; +} + +void mailimap_set_free(struct mailimap_set * set) +{ + clist_foreach(set->set_list, (clist_func) mailimap_set_item_free, NULL); + clist_free(set->set_list); + free(set); +} + +/* SEARCH with date key */ +/* date */ + +struct mailimap_date * +mailimap_date_new(int dt_day, int dt_month, int dt_year) +{ + struct mailimap_date * date; + + date = malloc(sizeof(* date)); + if (date == NULL) + return NULL; + + date->dt_day = dt_day; + date->dt_month = dt_month; + date->dt_year = dt_year; + + return date; +} + +void mailimap_date_free(struct mailimap_date * date) +{ + free(date); +} + + + +struct mailimap_fetch_att * +mailimap_fetch_att_new(int att_type, struct mailimap_section * att_section, + uint32_t att_offset, uint32_t att_size) +{ + struct mailimap_fetch_att * fetch_att; + + fetch_att = malloc(sizeof(* fetch_att)); + if (fetch_att == NULL) + return NULL; + fetch_att->att_type = att_type; + fetch_att->att_section = att_section; + fetch_att->att_offset = att_offset; + fetch_att->att_size = att_size; + + return fetch_att; +} + +void mailimap_fetch_att_free(struct mailimap_fetch_att * fetch_att) +{ + if (fetch_att->att_section != NULL) + mailimap_section_free(fetch_att->att_section); + free(fetch_att); +} + + + +struct mailimap_fetch_type * +mailimap_fetch_type_new(int ft_type, + struct mailimap_fetch_att * ft_fetch_att, + clist * ft_fetch_att_list) +{ + struct mailimap_fetch_type * fetch_type; + + fetch_type = malloc(sizeof(* fetch_type)); + if (fetch_type == NULL) + return NULL; + fetch_type->ft_type = ft_type; + switch (ft_type) { + case MAILIMAP_FETCH_TYPE_FETCH_ATT: + fetch_type->ft_data.ft_fetch_att = ft_fetch_att; + break; + case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST: + fetch_type->ft_data.ft_fetch_att_list = ft_fetch_att_list; + break; + } + + return fetch_type; +} + +void mailimap_fetch_type_free(struct mailimap_fetch_type * fetch_type) +{ + switch (fetch_type->ft_type) { + case MAILIMAP_FETCH_TYPE_FETCH_ATT: + mailimap_fetch_att_free(fetch_type->ft_data.ft_fetch_att); + break; + case MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST: + clist_foreach(fetch_type->ft_data.ft_fetch_att_list, + (clist_func) mailimap_fetch_att_free, NULL); + clist_free(fetch_type->ft_data.ft_fetch_att_list); + break; + } + free(fetch_type); +} + + + + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new(int fl_sign, int fl_silent, + struct mailimap_flag_list * fl_flag_list) +{ + struct mailimap_store_att_flags * store_att_flags; + + store_att_flags = malloc(sizeof(* store_att_flags)); + if (store_att_flags == NULL) + return NULL; + + store_att_flags->fl_sign = fl_sign; + store_att_flags->fl_silent = fl_silent; + store_att_flags->fl_flag_list = fl_flag_list; + + return store_att_flags; +} + +void mailimap_store_att_flags_free(struct mailimap_store_att_flags * + store_att_flags) +{ + mailimap_flag_list_free(store_att_flags->fl_flag_list); + free(store_att_flags); +} + + +struct mailimap_search_key * +mailimap_search_key_new(int sk_type, + char * sk_bcc, struct mailimap_date * sk_before, char * sk_body, + char * sk_cc, char * sk_from, char * sk_keyword, + struct mailimap_date * sk_on, struct mailimap_date * sk_since, + char * sk_subject, char * sk_text, char * sk_to, + char * sk_unkeyword, char * sk_header_name, + char * sk_header_value, uint32_t sk_larger, + struct mailimap_search_key * sk_not, + struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2, + struct mailimap_date * sk_sentbefore, + struct mailimap_date * sk_senton, + struct mailimap_date * sk_sentsince, + uint32_t sk_smaller, struct mailimap_set * sk_uid, + struct mailimap_set * sk_set, clist * sk_multiple) +{ + struct mailimap_search_key * key; + + key = malloc(sizeof(* key)); + if (key == NULL) + return NULL; + + key->sk_type = sk_type; + switch (sk_type) { + case MAILIMAP_SEARCH_KEY_BCC: + key->sk_data.sk_bcc = sk_bcc; + break; + case MAILIMAP_SEARCH_KEY_BEFORE: + key->sk_data.sk_before = sk_before; + break; + case MAILIMAP_SEARCH_KEY_BODY: + key->sk_data.sk_body = sk_body; + break; + case MAILIMAP_SEARCH_KEY_CC: + key->sk_data.sk_cc = sk_cc; + break; + case MAILIMAP_SEARCH_KEY_FROM: + key->sk_data.sk_from = sk_from; + break; + case MAILIMAP_SEARCH_KEY_KEYWORD: + key->sk_data.sk_keyword = sk_keyword; + break; + case MAILIMAP_SEARCH_KEY_ON: + key->sk_data.sk_on = sk_on; + break; + case MAILIMAP_SEARCH_KEY_SINCE: + key->sk_data.sk_since = sk_since; + break; + case MAILIMAP_SEARCH_KEY_SUBJECT: + key->sk_data.sk_subject = sk_subject; + break; + case MAILIMAP_SEARCH_KEY_TEXT: + key->sk_data.sk_text = sk_text; + break; + case MAILIMAP_SEARCH_KEY_TO: + key->sk_data.sk_to = sk_to; + break; + case MAILIMAP_SEARCH_KEY_UNKEYWORD: + key->sk_data.sk_unkeyword = sk_unkeyword; + break; + case MAILIMAP_SEARCH_KEY_HEADER: + key->sk_data.sk_header.sk_header_name = sk_header_name; + key->sk_data.sk_header.sk_header_value = sk_header_value; + break; + case MAILIMAP_SEARCH_KEY_LARGER: + key->sk_data.sk_larger = sk_larger; + break; + case MAILIMAP_SEARCH_KEY_NOT: + key->sk_data.sk_not = sk_not; + break; + case MAILIMAP_SEARCH_KEY_OR: + key->sk_data.sk_or.sk_or1 = sk_or1; + key->sk_data.sk_or.sk_or2 = sk_or2; + break; + case MAILIMAP_SEARCH_KEY_SENTBEFORE: + key->sk_data.sk_sentbefore = sk_sentbefore; + break; + case MAILIMAP_SEARCH_KEY_SENTON: + key->sk_data.sk_senton = sk_senton; + break; + case MAILIMAP_SEARCH_KEY_SENTSINCE: + key->sk_data.sk_sentsince = sk_sentsince; + break; + case MAILIMAP_SEARCH_KEY_SMALLER: + key->sk_data.sk_smaller = sk_smaller; + break; + case MAILIMAP_SEARCH_KEY_UID: + key->sk_data.sk_uid = sk_uid; + break; + case MAILIMAP_SEARCH_KEY_SET: + key->sk_data.sk_set = sk_set; + break; + case MAILIMAP_SEARCH_KEY_MULTIPLE: + key->sk_data.sk_multiple = sk_multiple; + break; + } + return key; +} + + +void mailimap_search_key_free(struct mailimap_search_key * key) +{ + switch (key->sk_type) { + case MAILIMAP_SEARCH_KEY_BCC: + mailimap_astring_free(key->sk_data.sk_bcc); + break; + case MAILIMAP_SEARCH_KEY_BEFORE: + mailimap_date_free(key->sk_data.sk_before); + break; + case MAILIMAP_SEARCH_KEY_BODY: + mailimap_astring_free(key->sk_data.sk_body); + break; + case MAILIMAP_SEARCH_KEY_CC: + mailimap_astring_free(key->sk_data.sk_cc); + break; + case MAILIMAP_SEARCH_KEY_FROM: + mailimap_astring_free(key->sk_data.sk_from); + break; + case MAILIMAP_SEARCH_KEY_KEYWORD: + mailimap_flag_keyword_free(key->sk_data.sk_keyword); + break; + case MAILIMAP_SEARCH_KEY_ON: + mailimap_date_free(key->sk_data.sk_on); + break; + case MAILIMAP_SEARCH_KEY_SINCE: + mailimap_date_free(key->sk_data.sk_since); + break; + case MAILIMAP_SEARCH_KEY_SUBJECT: + mailimap_astring_free(key->sk_data.sk_subject); + break; + case MAILIMAP_SEARCH_KEY_TEXT: + mailimap_astring_free(key->sk_data.sk_text); + break; + case MAILIMAP_SEARCH_KEY_TO: + mailimap_astring_free(key->sk_data.sk_to); + break; + case MAILIMAP_SEARCH_KEY_UNKEYWORD: + mailimap_flag_keyword_free(key->sk_data.sk_unkeyword); + break; + case MAILIMAP_SEARCH_KEY_HEADER: + mailimap_header_fld_name_free(key->sk_data.sk_header.sk_header_name); + mailimap_astring_free(key->sk_data.sk_header.sk_header_value); + break; + case MAILIMAP_SEARCH_KEY_NOT: + mailimap_search_key_free(key->sk_data.sk_not); + break; + case MAILIMAP_SEARCH_KEY_OR: + mailimap_search_key_free(key->sk_data.sk_or.sk_or1); + mailimap_search_key_free(key->sk_data.sk_or.sk_or2); + break; + case MAILIMAP_SEARCH_KEY_SENTBEFORE: + mailimap_date_free(key->sk_data.sk_sentbefore); + break; + case MAILIMAP_SEARCH_KEY_SENTON: + mailimap_date_free(key->sk_data.sk_senton); + break; + case MAILIMAP_SEARCH_KEY_SENTSINCE: + mailimap_date_free(key->sk_data.sk_sentsince); + break; + case MAILIMAP_SEARCH_KEY_UID: + mailimap_set_free(key->sk_data.sk_uid); + break; + case MAILIMAP_SEARCH_KEY_SET: + mailimap_set_free(key->sk_data.sk_set); + break; + case MAILIMAP_SEARCH_KEY_MULTIPLE: + clist_foreach(key->sk_data.sk_multiple, + (clist_func) mailimap_search_key_free, NULL); + clist_free(key->sk_data.sk_multiple); + break; + } + + free(key); +} + + + + + + + + +struct mailimap_status_att_list * +mailimap_status_att_list_new(clist * att_list) +{ + struct mailimap_status_att_list * status_att_list; + + status_att_list = malloc(sizeof(* status_att_list)); + if (status_att_list == NULL) + return NULL; + status_att_list->att_list = att_list; + + return status_att_list; +} + +void mailimap_status_att_list_free(struct mailimap_status_att_list * + status_att_list) +{ + clist_foreach(status_att_list->att_list, (clist_func) free, NULL); + clist_free(status_att_list->att_list); + free(status_att_list); +} + + + + +/* main */ + + +struct mailimap_selection_info * +mailimap_selection_info_new(void) +{ + struct mailimap_selection_info * sel_info; + + sel_info = malloc(sizeof(* sel_info)); + if (sel_info == NULL) + return NULL; + + sel_info->sel_perm_flags = NULL; + sel_info->sel_perm = MAILIMAP_MAILBOX_READWRITE; + sel_info->sel_uidnext = 0; + sel_info->sel_uidvalidity = 0; + sel_info->sel_first_unseen = 0; + sel_info->sel_flags = NULL; + sel_info->sel_exists = 0; + sel_info->sel_recent = 0; + sel_info->sel_unseen = 0; + + return sel_info; +} + +void +mailimap_selection_info_free(struct mailimap_selection_info * sel_info) +{ + if (sel_info->sel_perm_flags != NULL) { + clist_foreach(sel_info->sel_perm_flags, + (clist_func) mailimap_flag_perm_free, NULL); + clist_free(sel_info->sel_perm_flags); + } + if (sel_info->sel_flags) + mailimap_flag_list_free(sel_info->sel_flags); + + free(sel_info); +} + +struct mailimap_connection_info * +mailimap_connection_info_new(void) +{ + struct mailimap_connection_info * conn_info; + + conn_info = malloc(sizeof(* conn_info)); + if (conn_info == NULL) + return NULL; + + conn_info->imap_capability = NULL; + + return conn_info; +} + +void +mailimap_connection_info_free(struct mailimap_connection_info * conn_info) +{ + if (conn_info->imap_capability != NULL) + mailimap_capability_data_free(conn_info->imap_capability); + free(conn_info); +} + +struct mailimap_response_info * +mailimap_response_info_new(void) +{ + struct mailimap_response_info * resp_info; + + resp_info = malloc(sizeof(* resp_info)); + if (resp_info == NULL) + goto err; + + resp_info->rsp_alert = NULL; + resp_info->rsp_parse = NULL; + resp_info->rsp_badcharset = NULL; + resp_info->rsp_trycreate = FALSE; + resp_info->rsp_mailbox_list = clist_new(); + resp_info->rsp_extension_list = clist_new(); + if (resp_info->rsp_extension_list == NULL) + goto free; + resp_info->rsp_mailbox_lsub = clist_new(); + if (resp_info->rsp_mailbox_lsub == NULL) + goto free_mb_list; + resp_info->rsp_search_result = clist_new(); + if (resp_info->rsp_search_result == NULL) + goto free_mb_lsub; + resp_info->rsp_status = NULL; + resp_info->rsp_expunged = clist_new(); + if (resp_info->rsp_expunged == NULL) + goto free_search_result; + resp_info->rsp_fetch_list = clist_new(); + if (resp_info->rsp_fetch_list == NULL) + goto free_expunged; + resp_info->rsp_atom = NULL; + resp_info->rsp_value = NULL; + + return resp_info; + + free_expunged: + clist_free(resp_info->rsp_expunged); + free_search_result: + clist_free(resp_info->rsp_search_result); + free_mb_lsub: + clist_free(resp_info->rsp_mailbox_lsub); + free_mb_list: + clist_free(resp_info->rsp_mailbox_list); + free: + free(resp_info); + err: + return NULL; +} + +void +mailimap_response_info_free(struct mailimap_response_info * resp_info) +{ + free(resp_info->rsp_value); + free(resp_info->rsp_atom); + if (resp_info->rsp_alert != NULL) + free(resp_info->rsp_alert); + if (resp_info->rsp_parse != NULL) + free(resp_info->rsp_parse); + if (resp_info->rsp_badcharset != NULL) { + clist_foreach(resp_info->rsp_badcharset, + (clist_func) mailimap_astring_free, NULL); + clist_free(resp_info->rsp_badcharset); + } + if (resp_info->rsp_mailbox_list != NULL) { + clist_foreach(resp_info->rsp_mailbox_list, + (clist_func) mailimap_mailbox_list_free, NULL); + clist_free(resp_info->rsp_mailbox_list); + } + if (resp_info->rsp_extension_list != NULL) { + clist_foreach(resp_info->rsp_extension_list, + (clist_func) mailimap_extension_data_free, NULL); + clist_free(resp_info->rsp_extension_list); + } + if (resp_info->rsp_mailbox_lsub != NULL) { + clist_foreach(resp_info->rsp_mailbox_lsub, + (clist_func) mailimap_mailbox_list_free, NULL); + clist_free(resp_info->rsp_mailbox_lsub); + } + if (resp_info->rsp_search_result != NULL) + mailimap_mailbox_data_search_free(resp_info->rsp_search_result); + if (resp_info->rsp_status != NULL) + mailimap_mailbox_data_status_free(resp_info->rsp_status); + if (resp_info->rsp_expunged != NULL) { + clist_foreach(resp_info->rsp_expunged, + (clist_func) mailimap_number_alloc_free, NULL); + clist_free(resp_info->rsp_expunged); + } + if (resp_info->rsp_fetch_list != NULL) { + clist_foreach(resp_info->rsp_fetch_list, + (clist_func) mailimap_msg_att_free, NULL); + clist_free(resp_info->rsp_fetch_list); + } + + free(resp_info); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3298 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_types.h,v 1.29 2006/10/20 00:13:30 hoa Exp $ + */ + +/* + IMAP4rev1 grammar + + address = "(" addr-name SP addr-adl SP addr-mailbox SP + addr-host ")" + + addr-adl = nstring + ; Holds route from [RFC-822] route-addr if + ; non-NIL + + addr-host = nstring + ; NIL indicates [RFC-822] group syntax. + ; Otherwise, holds [RFC-822] domain name + + addr-mailbox = nstring + ; NIL indicates end of [RFC-822] group; if + ; non-NIL and addr-host is NIL, holds + ; [RFC-822] group name. + ; Otherwise, holds [RFC-822] local-part + ; after removing [RFC-822] quoting + + + + addr-name = nstring + ; If non-NIL, holds phrase from [RFC-822] + ; mailbox after removing [RFC-822] quoting + + append = "APPEND" SP mailbox [SP flag-list] [SP date-time] SP + literal + + astring = 1*ASTRING-CHAR / string + + ASTRING-CHAR = ATOM-CHAR / resp-specials + + atom = 1*ATOM-CHAR + + ATOM-CHAR = <any CHAR except atom-specials> + + atom-specials = "(" / ")" / "{" / SP / CTL / list-wildcards / + quoted-specials / resp-specials + + authenticate = "AUTHENTICATE" SP auth-type *(CRLF base64) + + auth-type = atom + ; Defined by [SASL] + + base64 = *(4base64-char) [base64-terminal] + + base64-char = ALPHA / DIGIT / "+" / "/" + ; Case-sensitive + + base64-terminal = (2base64-char "==") / (3base64-char "=") + + body = "(" (body-type-1part / body-type-mpart) ")" + + body-extension = nstring / number / + "(" body-extension *(SP body-extension) ")" + ; Future expansion. Client implementations + ; MUST accept body-extension fields. Server + ; implementations MUST NOT generate + ; body-extension fields except as defined by + ; future standard or standards-track + ; revisions of this specification. + + body-ext-1part = body-fld-md5 [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + + body-ext-mpart = body-fld-param [SP body-fld-dsp [SP body-fld-lang + *(SP body-extension)]] + ; MUST NOT be returned on non-extensible + ; "BODY" fetch + + body-fields = body-fld-param SP body-fld-id SP body-fld-desc SP + body-fld-enc SP body-fld-octets + + body-fld-desc = nstring + + body-fld-dsp = "(" string SP body-fld-param ")" / nil + + body-fld-enc = (DQUOTE ("7BIT" / "8BIT" / "BINARY" / "BASE64"/ + "QUOTED-PRINTABLE") DQUOTE) / string + + body-fld-id = nstring + + body-fld-lang = nstring / "(" string *(SP string) ")" + + body-fld-lines = number + + body-fld-md5 = nstring + + body-fld-octets = number + + body-fld-param = "(" string SP string *(SP string SP string) ")" / nil + + body-type-1part = (body-type-basic / body-type-msg / body-type-text) + [SP body-ext-1part] + + body-type-basic = media-basic SP body-fields + ; MESSAGE subtype MUST NOT be "RFC822" + + body-type-mpart = 1*body SP media-subtype + [SP body-ext-mpart] + + body-type-msg = media-message SP body-fields SP envelope + SP body SP body-fld-lines + + body-type-text = media-text SP body-fields SP body-fld-lines + + capability = ("AUTH=" auth-type) / atom + ; New capabilities MUST begin with "X" or be + ; registered with IANA as standard or + ; standards-track + + + capability-data = "CAPABILITY" *(SP capability) SP "IMAP4rev1" + *(SP capability) + ; IMAP4rev1 servers which offer RFC 1730 + ; compatibility MUST list "IMAP4" as the first + ; capability. + + CHAR8 = %x01-ff + ; any OCTET except NUL, %x00 + + command = tag SP (command-any / command-auth / command-nonauth / + command-select) CRLF + ; Modal based on state + + command-any = "CAPABILITY" / "LOGOUT" / "NOOP" / x-command + ; Valid in all states + + command-auth = append / create / delete / examine / list / lsub / + rename / select / status / subscribe / unsubscribe + ; Valid only in Authenticated or Selected state + + command-nonauth = login / authenticate + ; Valid only when in Not Authenticated state + + command-select = "CHECK" / "CLOSE" / "EXPUNGE" / copy / fetch / store / + uid / search + ; Valid only when in Selected state + + continue-req = "+" SP (resp-text / base64) CRLF + + copy = "COPY" SP set SP mailbox + + create = "CREATE" SP mailbox + ; Use of INBOX gives a NO error + + date = date-text / DQUOTE date-text DQUOTE + + date-day = 1*2DIGIT + ; Day of month + + date-day-fixed = (SP DIGIT) / 2DIGIT + ; Fixed-format version of date-day + + date-month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / + "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec" + + date-text = date-day "-" date-month "-" date-year + + date-year = 4DIGIT + + date-time = DQUOTE date-day-fixed "-" date-month "-" date-year + SP time SP zone DQUOTE + + delete = "DELETE" SP mailbox + ; Use of INBOX gives a NO error + + digit-nz = %x31-39 + ; 1-9 + + envelope = "(" env-date SP env-subject SP env-from SP env-sender SP + env-reply-to SP env-to SP env-cc SP env-bcc SP + env-in-reply-to SP env-message-id ")" + + env-bcc = "(" 1*address ")" / nil + + env-cc = "(" 1*address ")" / nil + + env-date = nstring + + env-from = "(" 1*address ")" / nil + + env-in-reply-to = nstring + + env-message-id = nstring + + env-reply-to = "(" 1*address ")" / nil + + env-sender = "(" 1*address ")" / nil + + env-subject = nstring + + env-to = "(" 1*address ")" / nil + + examine = "EXAMINE" SP mailbox + + fetch = "FETCH" SP set SP ("ALL" / "FULL" / "FAST" / fetch-att / + "(" fetch-att *(SP fetch-att) ")") + + fetch-att = "ENVELOPE" / "FLAGS" / "INTERNALDATE" / + "RFC822" [".HEADER" / ".SIZE" / ".TEXT"] / + "BODY" ["STRUCTURE"] / "UID" / + "BODY" [".PEEK"] section ["<" number "." nz-number ">"] + + flag = "\Answered" / "\Flagged" / "\Deleted" / + "\Seen" / "\Draft" / flag-keyword / flag-extension + ; Does not include "\Recent" + + flag-extension = "\" atom + ; Future expansion. Client implementations + ; MUST accept flag-extension flags. Server + ; implementations MUST NOT generate + ; flag-extension flags except as defined by + ; future standard or standards-track + ; revisions of this specification. + + flag-fetch = flag / "\Recent" + + flag-keyword = atom + + flag-list = "(" [flag *(SP flag)] ")" + + flag-perm = flag / "\*" + + greeting = "*" SP (resp-cond-auth / resp-cond-bye) CRLF + + header-fld-name = astring + + header-list = "(" header-fld-name *(SP header-fld-name) ")" + + list = "LIST" SP mailbox SP list-mailbox + + list-mailbox = 1*list-char / string + + list-char = ATOM-CHAR / list-wildcards / resp-specials + + list-wildcards = "%" / "*" + + literal = "{" number "}" CRLF *CHAR8 + ; Number represents the number of CHAR8s + + login = "LOGIN" SP userid SP password + + lsub = "LSUB" SP mailbox SP list-mailbox + + mailbox = "INBOX" / astring + ; INBOX is case-insensitive. All case variants of + ; INBOX (e.g. "iNbOx") MUST be interpreted as INBOX + ; not as an astring. An astring which consists of + ; the case-insensitive sequence "I" "N" "B" "O" "X" + ; is considered to be INBOX and not an astring. + ; Refer to section 5.1 for further + ; semantic details of mailbox names. + + mailbox-data = "FLAGS" SP flag-list / "LIST" SP mailbox-list / + "LSUB" SP mailbox-list / "SEARCH" *(SP nz-number) / + "STATUS" SP mailbox SP "(" + [status-att SP number *(SP status-att SP number)] ")" / + number SP "EXISTS" / number SP "RECENT" + + mailbox-list = "(" [mbx-list-flags] ")" SP + (DQUOTE QUOTED-CHAR DQUOTE / nil) SP mailbox + + mbx-list-flags = *(mbx-list-oflag SP) mbx-list-sflag + *(SP mbx-list-oflag) / + mbx-list-oflag *(SP mbx-list-oflag) + + mbx-list-oflag = "\Noinferiors" / flag-extension + ; Other flags; multiple possible per LIST response + + mbx-list-sflag = "\Noselect" / "\Marked" / "\Unmarked" + ; Selectability flags; only one per LIST response + + media-basic = ((DQUOTE ("APPLICATION" / "AUDIO" / "IMAGE" / "MESSAGE" / + "VIDEO") DQUOTE) / string) SP media-subtype + ; Defined in [MIME-IMT] + + media-message = DQUOTE "MESSAGE" DQUOTE SP DQUOTE "RFC822" DQUOTE + ; Defined in [MIME-IMT] + + media-subtype = string + ; Defined in [MIME-IMT] + + media-text = DQUOTE "TEXT" DQUOTE SP media-subtype + ; Defined in [MIME-IMT] + + message-data = nz-number SP ("EXPUNGE" / ("FETCH" SP msg-att)) + + msg-att = "(" (msg-att-dynamic / msg-att-static) + *(SP (msg-att-dynamic / msg-att-static)) ")" + + msg-att-dynamic = "FLAGS" SP "(" [flag-fetch *(SP flag-fetch)] ")" + ; MAY change for a message + + msg-att-static = "ENVELOPE" SP envelope / "INTERNALDATE" SP date-time / + "RFC822" [".HEADER" / ".TEXT"] SP nstring / + "RFC822.SIZE" SP number / "BODY" ["STRUCTURE"] SP body / + "BODY" section ["<" number ">"] SP nstring / + "UID" SP uniqueid + ; MUST NOT change for a message + + nil = "NIL" + + nstring = string / nil + + number = 1*DIGIT + ; Unsigned 32-bit integer + ; (0 <= n < 4,294,967,296) + + nz-number = digit-nz *DIGIT + ; Non-zero unsigned 32-bit integer + ; (0 < n < 4,294,967,296) + + password = astring + + quoted = DQUOTE *QUOTED-CHAR DQUOTE + + QUOTED-CHAR = <any TEXT-CHAR except quoted-specials> / + "\" quoted-specials + + quoted-specials = DQUOTE / "\" + + rename = "RENAME" SP mailbox SP mailbox + ; Use of INBOX as a destination gives a NO error + + response = *(continue-req / response-data) response-done + + response-data = "*" SP (resp-cond-state / resp-cond-bye / + mailbox-data / message-data / capability-data) CRLF + + response-done = response-tagged / response-fatal + + response-fatal = "*" SP resp-cond-bye CRLF + ; Server closes connection immediately + + response-tagged = tag SP resp-cond-state CRLF + + resp-cond-auth = ("OK" / "PREAUTH") SP resp-text + ; Authentication condition + + resp-cond-bye = "BYE" SP resp-text + + resp-cond-state = ("OK" / "NO" / "BAD") SP resp-text + ; Status condition + + resp-specials = "]" + + resp-text = ["[" resp-text-code "]" SP] text + + resp-text-code = "ALERT" / + "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / + capability-data / "PARSE" / + "PERMANENTFLAGS" SP "(" [flag-perm *(SP flag-perm)] ")" / + "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / + "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / + "UNSEEN" SP nz-number / + atom [SP 1*<any TEXT-CHAR except "]">] + + search = "SEARCH" [SP "CHARSET" SP astring] 1*(SP search-key) + ; CHARSET argument to MUST be registered with IANA + + search-key = "ALL" / "ANSWERED" / "BCC" SP astring / + "BEFORE" SP date / "BODY" SP astring / + "CC" SP astring / "DELETED" / "FLAGGED" / + "FROM" SP astring / "KEYWORD" SP flag-keyword / "NEW" / + "OLD" / "ON" SP date / "RECENT" / "SEEN" / + "SINCE" SP date / "SUBJECT" SP astring / + "TEXT" SP astring / "TO" SP astring / + "UNANSWERED" / "UNDELETED" / "UNFLAGGED" / + "UNKEYWORD" SP flag-keyword / "UNSEEN" / + ; Above this line were in [IMAP2] + "DRAFT" / "HEADER" SP header-fld-name SP astring / + "LARGER" SP number / "NOT" SP search-key / + "OR" SP search-key SP search-key / + "SENTBEFORE" SP date / "SENTON" SP date / + "SENTSINCE" SP date / "SMALLER" SP number / + "UID" SP set / "UNDRAFT" / set / + "(" search-key *(SP search-key) ")" + + section = "[" [section-spec] "]" + + section-msgtext = "HEADER" / "HEADER.FIELDS" [".NOT"] SP header-list / + "TEXT" + ; top-level or MESSAGE/RFC822 part + + section-part = nz-number *("." nz-number) + ; body part nesting + + section-spec = section-msgtext / (section-part ["." section-text]) + + section-text = section-msgtext / "MIME" + ; text other than actual body part (headers, etc.) + + select = "SELECT" SP mailbox + + sequence-num = nz-number / "*" + ; * is the largest number in use. For message + ; sequence numbers, it is the number of messages + ; in the mailbox. For unique identifiers, it is + ; the unique identifier of the last message in + ; the mailbox. + + set = sequence-num / (sequence-num ":" sequence-num) / + (set "," set) + ; Identifies a set of messages. For message + ; sequence numbers, these are consecutive + ; numbers from 1 to the number of messages in + ; the mailbox + ; Comma delimits individual numbers, colon + ; delimits between two numbers inclusive. + ; Example: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13, + ; 14,15 for a mailbox with 15 messages. + + + status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")" + + status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / + "UNSEEN" + + store = "STORE" SP set SP store-att-flags + + store-att-flags = (["+" / "-"] "FLAGS" [".SILENT"]) SP + (flag-list / (flag *(SP flag))) + + string = quoted / literal + + subscribe = "SUBSCRIBE" SP mailbox + + tag = 1*<any ASTRING-CHAR except "+"> + + text = 1*TEXT-CHAR + + TEXT-CHAR = <any CHAR except CR and LF> + + time = 2DIGIT ":" 2DIGIT ":" 2DIGIT + ; Hours minutes seconds + + uid = "UID" SP (copy / fetch / search / store) + ; Unique identifiers used instead of message + ; sequence numbers + + uniqueid = nz-number + ; Strictly ascending + + unsubscribe = "UNSUBSCRIBE" SP mailbox + + userid = astring + + x-command = "X" atom <experimental command arguments> + + zone = ("+" / "-") 4DIGIT + ; Signed four-digit value of hhmm representing + ; hours and minutes east of Greenwich (that is, + ; the amount that the given time differs from + ; Universal Time). Subtracting the timezone + ; from the given time will give the UT form. + ; The Universal Time zone is "+0000". +*/ + + +#ifndef MAILIMAP_TYPES_H + +#define MAILIMAP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/libetpan-config.h> +#include <libetpan/mailstream.h> +#include <libetpan/clist.h> + + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + + +/* + mailimap_address represents a mail address + + - personal_name is the name to display in an address + '"name"' in '"name" <address@domain>', should be allocated + with a malloc() + + - source_route is the source-route information in the + mail address (RFC 822), should be allocated with a malloc() + + - mailbox_name is the name of the mailbox 'address' in + '"name" <address@domain>', should be allocated with a malloc() + + - host_name is the name of the host 'domain' in + '"name" <address@domain>', should be allocated with a malloc() + + if mailbox_name is not NULL and host_name is NULL, this is the name + of a group, the next addresses in the list are elements of the group + until we reach an address with a NULL mailbox_name. +*/ + +struct mailimap_address { + char * ad_personal_name; /* can be NULL */ + char * ad_source_route; /* can be NULL */ + char * ad_mailbox_name; /* can be NULL */ + char * ad_host_name; /* can be NULL */ +}; + + +struct mailimap_address * +mailimap_address_new(char * ad_personal_name, char * ad_source_route, + char * ad_mailbox_name, char * ad_host_name); + +void mailimap_address_free(struct mailimap_address * addr); + + +/* this is the type of MIME body parsed by IMAP server */ + +enum { + MAILIMAP_BODY_ERROR, + MAILIMAP_BODY_1PART, /* single part */ + MAILIMAP_BODY_MPART /* multi-part */ +}; + +/* + mailimap_body represent a MIME body parsed by IMAP server + + - type is the type of the MIME part (single part or multipart) + + - body_1part is defined if this is a single part + + - body_mpart is defined if this is a multipart +*/ + +struct mailimap_body { + int bd_type; + /* can be MAILIMAP_BODY_1PART or MAILIMAP_BODY_MPART */ + union { + struct mailimap_body_type_1part * bd_body_1part; /* can be NULL */ + struct mailimap_body_type_mpart * bd_body_mpart; /* can be NULL */ + } bd_data; +}; + + +struct mailimap_body * +mailimap_body_new(int bd_type, + struct mailimap_body_type_1part * bd_body_1part, + struct mailimap_body_type_mpart * bd_body_mpart); + +void mailimap_body_free(struct mailimap_body * body); + + + +/* + this is the type of MIME body extension +*/ + +enum { + MAILIMAP_BODY_EXTENSION_ERROR, + MAILIMAP_BODY_EXTENSION_NSTRING, /* string */ + MAILIMAP_BODY_EXTENSION_NUMBER, /* number */ + MAILIMAP_BODY_EXTENSION_LIST /* list of + (struct mailimap_body_extension *) */ +}; + +/* + mailimap_body_extension is a future extension header field value + + - type is the type of the body extension (string, number or + list of extension) + + - nstring is a string value if the type is string + + - number is a integer value if the type is number + + - list is a list of body extension if the type is a list +*/ + +struct mailimap_body_extension { + int ext_type; + /* + can be MAILIMAP_BODY_EXTENSION_NSTRING, MAILIMAP_BODY_EXTENSION_NUMBER + or MAILIMAP_BODY_EXTENSION_LIST + */ + union { + char * ext_nstring; /* can be NULL */ + uint32_t ext_number; + clist * ext_body_extension_list; + /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ + } ext_data; +}; + +struct mailimap_body_extension * +mailimap_body_extension_new(int ext_type, char * ext_nstring, + uint32_t ext_number, + clist * ext_body_extension_list); + +void mailimap_body_extension_free(struct mailimap_body_extension * be); + + +/* + mailimap_body_ext_1part is the extended result part of a single part + bodystructure. + + - body_md5 is the value of the Content-MD5 header field, should be + allocated with malloc() + + - body_disposition is the value of the Content-Disposition header field + + - body_language is the value of the Content-Language header field + + - body_extension_list is the list of extension fields value. +*/ + +struct mailimap_body_ext_1part { + char * bd_md5; /* != NULL */ + struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */ + struct mailimap_body_fld_lang * bd_language; /* can be NULL */ + + clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ +}; + +struct mailimap_body_ext_1part * +mailimap_body_ext_1part_new(char * bd_md5, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + clist * bd_extension_list); + + +void +mailimap_body_ext_1part_free(struct mailimap_body_ext_1part * body_ext_1part); + + +/* + mailimap_body_ext_mpart is the extended result part of a multipart + bodystructure. + + - body_parameter is the list of parameters of Content-Type header field + + - body_disposition is the value of Content-Disposition header field + + - body_language is the value of Content-Language header field + + - body_extension_list is the list of extension fields value. +*/ + +struct mailimap_body_ext_mpart { + struct mailimap_body_fld_param * bd_parameter; /* != NULL */ + struct mailimap_body_fld_dsp * bd_disposition; /* can be NULL */ + struct mailimap_body_fld_lang * bd_language; /* can be NULL */ + clist * bd_extension_list; /* list of (struct mailimap_body_extension *) */ + /* can be NULL */ +}; + +struct mailimap_body_ext_mpart * +mailimap_body_ext_mpart_new(struct mailimap_body_fld_param * bd_parameter, + struct mailimap_body_fld_dsp * bd_disposition, + struct mailimap_body_fld_lang * bd_language, + clist * bd_extension_list); + +void +mailimap_body_ext_mpart_free(struct mailimap_body_ext_mpart * body_ext_mpart); + + +/* + mailimap_body_fields is the MIME fields of a MIME part. + + - body_parameter is the list of parameters of Content-Type header field + + - body_id is the value of Content-ID header field, should be allocated + with malloc() + + - body_description is the value of Content-Description header field, + should be allocated with malloc() + + - body_encoding is the value of Content-Transfer-Encoding header field + + - body_disposition is the value of Content-Disposition header field + + - body_size is the size of the MIME part +*/ + +struct mailimap_body_fields { + struct mailimap_body_fld_param * bd_parameter; /* != NULL */ + char * bd_id; /* can be NULL */ + char * bd_description; /* can be NULL */ + struct mailimap_body_fld_enc * bd_encoding; /* != NULL */ + uint32_t bd_size; +}; + +struct mailimap_body_fields * +mailimap_body_fields_new(struct mailimap_body_fld_param * bd_parameter, + char * bd_id, + char * bd_description, + struct mailimap_body_fld_enc * bd_encoding, + uint32_t bd_size); + +void +mailimap_body_fields_free(struct mailimap_body_fields * body_fields); + + + +/* + mailimap_body_fld_dsp is the parsed value of the Content-Disposition field + + - disposition_type is the type of Content-Disposition + (usually attachment or inline), should be allocated with malloc() + + - attributes is the list of Content-Disposition attributes +*/ + +struct mailimap_body_fld_dsp { + char * dsp_type; /* != NULL */ + struct mailimap_body_fld_param * dsp_attributes; /* != NULL */ +}; + +struct mailimap_body_fld_dsp * +mailimap_body_fld_dsp_new(char * dsp_type, + struct mailimap_body_fld_param * dsp_attributes); + +void mailimap_body_fld_dsp_free(struct mailimap_body_fld_dsp * bfd); + + + +/* these are the different parsed values for Content-Transfer-Encoding */ + +enum { + MAILIMAP_BODY_FLD_ENC_7BIT, /* 7bit */ + MAILIMAP_BODY_FLD_ENC_8BIT, /* 8bit */ + MAILIMAP_BODY_FLD_ENC_BINARY, /* binary */ + MAILIMAP_BODY_FLD_ENC_BASE64, /* base64 */ + MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE, /* quoted-printable */ + MAILIMAP_BODY_FLD_ENC_OTHER /* other */ +}; + +/* + mailimap_body_fld_enc is a parsed value for Content-Transfer-Encoding + + - type is the kind of Content-Transfer-Encoding, this can be + MAILIMAP_BODY_FLD_ENC_7BIT, MAILIMAP_BODY_FLD_ENC_8BIT, + MAILIMAP_BODY_FLD_ENC_BINARY, MAILIMAP_BODY_FLD_ENC_BASE64, + MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE or MAILIMAP_BODY_FLD_ENC_OTHER + + - in case of MAILIMAP_BODY_FLD_ENC_OTHER, this value is defined, + should be allocated with malloc() +*/ + +struct mailimap_body_fld_enc { + int enc_type; + char * enc_value; /* can be NULL */ +}; + +struct mailimap_body_fld_enc * +mailimap_body_fld_enc_new(int enc_type, char * enc_value); + +void mailimap_body_fld_enc_free(struct mailimap_body_fld_enc * bfe); + + +/* this is the type of Content-Language header field value */ + +enum { + MAILIMAP_BODY_FLD_LANG_ERROR, /* error parse */ + MAILIMAP_BODY_FLD_LANG_SINGLE, /* single value */ + MAILIMAP_BODY_FLD_LANG_LIST /* list of values */ +}; + +/* + mailimap_body_fld_lang is the parsed value of the Content-Language field + + - type is the type of content, this can be MAILIMAP_BODY_FLD_LANG_SINGLE + if this is a single value or MAILIMAP_BODY_FLD_LANG_LIST if there are + several values + + - single is the single value if the type is MAILIMAP_BODY_FLD_LANG_SINGLE, + should be allocated with malloc() + + - list is the list of value if the type is MAILIMAP_BODY_FLD_LANG_LIST, + all elements of the list should be allocated with malloc() +*/ + +struct mailimap_body_fld_lang { + int lg_type; + union { + char * lg_single; /* can be NULL */ + clist * lg_list; /* list of string (char *), can be NULL */ + } lg_data; +}; + +struct mailimap_body_fld_lang * +mailimap_body_fld_lang_new(int lg_type, char * lg_single, clist * lg_list); + +void +mailimap_body_fld_lang_free(struct mailimap_body_fld_lang * fld_lang); + + + +/* + mailimap_single_body_fld_param is a body field parameter + + - name is the name of the parameter, should be allocated with malloc() + + - value is the value of the parameter, should be allocated with malloc() +*/ + +struct mailimap_single_body_fld_param { + char * pa_name; /* != NULL */ + char * pa_value; /* != NULL */ +}; + +struct mailimap_single_body_fld_param * +mailimap_single_body_fld_param_new(char * pa_name, char * pa_value); + +void +mailimap_single_body_fld_param_free(struct mailimap_single_body_fld_param * p); + + +/* + mailmap_body_fld_param is a list of parameters + + - list is the list of parameters. +*/ + +struct mailimap_body_fld_param { + clist * pa_list; /* list of (struct mailimap_single_body_fld_param *) */ + /* != NULL */ +}; + +struct mailimap_body_fld_param * +mailimap_body_fld_param_new(clist * pa_list); + +void +mailimap_body_fld_param_free(struct mailimap_body_fld_param * fld_param); + + +/* + this is the kind of single part: a text part + (when Content-Type is text/xxx), a message part (when Content-Type is + message/rfc2822) or a basic part (others than multpart/xxx) +*/ + +enum { + MAILIMAP_BODY_TYPE_1PART_ERROR, /* parse error */ + MAILIMAP_BODY_TYPE_1PART_BASIC, /* others then multipart/xxx */ + MAILIMAP_BODY_TYPE_1PART_MSG, /* message/rfc2822 */ + MAILIMAP_BODY_TYPE_1PART_TEXT /* text/xxx */ +}; + + +/* + mailimap_body_type_1part is + + - type is the kind of single part, this can be + MAILIMAP_BODY_TYPE_1PART_BASIC, MAILIMAP_BODY_TYPE_1PART_MSG or + MAILIMAP_BODY_TYPE_1PART_TEXT. + + - body_type_basic is the basic part when type is + MAILIMAP_BODY_TYPE_1PART_BASIC + + - body_type_msg is the message part when type is + MAILIMAP_BODY_TYPE_1PART_MSG + + - body_type_text is the text part when type is + MAILIMAP_BODY_TYPE_1PART_TEXT +*/ + +struct mailimap_body_type_1part { + int bd_type; + union { + struct mailimap_body_type_basic * bd_type_basic; /* can be NULL */ + struct mailimap_body_type_msg * bd_type_msg; /* can be NULL */ + struct mailimap_body_type_text * bd_type_text; /* can be NULL */ + } bd_data; + struct mailimap_body_ext_1part * bd_ext_1part; /* can be NULL */ +}; + +struct mailimap_body_type_1part * +mailimap_body_type_1part_new(int bd_type, + struct mailimap_body_type_basic * bd_type_basic, + struct mailimap_body_type_msg * bd_type_msg, + struct mailimap_body_type_text * bd_type_text, + struct mailimap_body_ext_1part * bd_ext_1part); + +void +mailimap_body_type_1part_free(struct mailimap_body_type_1part * bt1p); + + + +/* + mailimap_body_type_basic is a basic field (with Content-Type other + than multipart/xxx, message/rfc2822 and text/xxx + + - media_basic will be the MIME type of the part + + - body_fields will be the parsed fields of the MIME part +*/ + +struct mailimap_body_type_basic { + struct mailimap_media_basic * bd_media_basic; /* != NULL */ + struct mailimap_body_fields * bd_fields; /* != NULL */ +}; + +struct mailimap_body_type_basic * +mailimap_body_type_basic_new(struct mailimap_media_basic * bd_media_basic, + struct mailimap_body_fields * bd_fields); + +void mailimap_body_type_basic_free(struct mailimap_body_type_basic * + body_type_basic); + +/* + mailimap_body_type_mpart is a MIME multipart. + + - body_list is the list of sub-parts. + + - media_subtype is the subtype of the multipart (for example + in multipart/alternative, this is "alternative") + + - body_ext_mpart is the extended fields of the MIME multipart +*/ + +struct mailimap_body_type_mpart { + clist * bd_list; /* list of (struct mailimap_body *) */ + /* != NULL */ + char * bd_media_subtype; /* != NULL */ + struct mailimap_body_ext_mpart * bd_ext_mpart; /* can be NULL */ +}; + +struct mailimap_body_type_mpart * +mailimap_body_type_mpart_new(clist * bd_list, char * bd_media_subtype, + struct mailimap_body_ext_mpart * bd_ext_mpart); + +void mailimap_body_type_mpart_free(struct mailimap_body_type_mpart * + body_type_mpart); + +/* + mailimap_body_type_msg is a MIME message part + + - body_fields is the MIME fields of the MIME message part + + - envelope is the list of parsed RFC 822 fields of the MIME message + + - body is the sub-part of the message + + - body_lines is the number of lines of the message part +*/ + +struct mailimap_body_type_msg { + struct mailimap_body_fields * bd_fields; /* != NULL */ + struct mailimap_envelope * bd_envelope; /* != NULL */ + struct mailimap_body * bd_body; /* != NULL */ + uint32_t bd_lines; +}; + +struct mailimap_body_type_msg * +mailimap_body_type_msg_new(struct mailimap_body_fields * bd_fields, + struct mailimap_envelope * bd_envelope, + struct mailimap_body * bd_body, + uint32_t bd_lines); + +void +mailimap_body_type_msg_free(struct mailimap_body_type_msg * body_type_msg); + + + +/* + mailimap_body_type_text is a single MIME part where Content-Type is text/xxx + + - media-text is the subtype of the text part (for example, in "text/plain", + this is "plain", should be allocated with malloc() + + - body_fields is the MIME fields of the MIME message part + + - body_lines is the number of lines of the message part +*/ + +struct mailimap_body_type_text { + char * bd_media_text; /* != NULL */ + struct mailimap_body_fields * bd_fields; /* != NULL */ + uint32_t bd_lines; +}; + +struct mailimap_body_type_text * +mailimap_body_type_text_new(char * bd_media_text, + struct mailimap_body_fields * bd_fields, + uint32_t bd_lines); + +void +mailimap_body_type_text_free(struct mailimap_body_type_text * body_type_text); + + + +/* this is the type of capability field */ + +enum { + MAILIMAP_CAPABILITY_AUTH_TYPE, /* when the capability is an + authentication type */ + MAILIMAP_CAPABILITY_NAME /* other type of capability */ +}; + +/* + mailimap_capability is a capability of the IMAP server + + - type is the type of capability, this is either a authentication type + (MAILIMAP_CAPABILITY_AUTH_TYPE) or an other type of capability + (MAILIMAP_CAPABILITY_NAME) + + - auth_type is a type of authentication "name" in "AUTH=name", + auth_type can be for example "PLAIN", when this is an authentication type, + should be allocated with malloc() + + - name is a type of capability when this is not an authentication type, + should be allocated with malloc() +*/ + +struct mailimap_capability { + int cap_type; + union { + char * cap_auth_type; /* can be NULL */ + char * cap_name; /* can be NULL */ + } cap_data; +}; + +struct mailimap_capability * +mailimap_capability_new(int cap_type, char * cap_auth_type, char * cap_name); + +void mailimap_capability_free(struct mailimap_capability * c); + + + + +/* + mailimap_capability_data is a list of capability + + - list is the list of capability +*/ + +struct mailimap_capability_data { + clist * cap_list; /* list of (struct mailimap_capability *), != NULL */ +}; + +struct mailimap_capability_data * +mailimap_capability_data_new(clist * cap_list); + +void +mailimap_capability_data_free(struct mailimap_capability_data * cap_data); + + + +/* this is the type of continue request data */ + +enum { + MAILIMAP_CONTINUE_REQ_ERROR, /* on parse error */ + MAILIMAP_CONTINUE_REQ_TEXT, /* when data is a text response */ + MAILIMAP_CONTINUE_REQ_BASE64 /* when data is a base64 response */ +}; + +/* + mailimap_continue_req is a continue request (a response prefixed by "+") + + - type is the type of continue request response + MAILIMAP_CONTINUE_REQ_TEXT (when information data is text), + MAILIMAP_CONTINUE_REQ_BASE64 (when information data is base64) + + - text is the information of type text in case of text data + + - base64 is base64 encoded data in the other case, should be allocated + with malloc() +*/ + +struct mailimap_continue_req { + int cr_type; + union { + struct mailimap_resp_text * cr_text; /* can be NULL */ + char * cr_base64; /* can be NULL */ + } cr_data; +}; + +struct mailimap_continue_req * +mailimap_continue_req_new(int cr_type, struct mailimap_resp_text * cr_text, + char * cr_base64); + +void mailimap_continue_req_free(struct mailimap_continue_req * cont_req); + + +/* + mailimap_date_time is a date + + - day is the day of month (1 to 31) + + - month (1 to 12) + + - year (4 digits) + + - hour (0 to 23) + + - min (0 to 59) + + - sec (0 to 59) + + - zone (this is the decimal value that we can read, for example: + for "-0200", the value is -200) +*/ + +struct mailimap_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +struct mailimap_date_time * +mailimap_date_time_new(int dt_day, int dt_month, int dt_year, int dt_hour, + int dt_min, int dt_sec, int dt_zone); + +void mailimap_date_time_free(struct mailimap_date_time * date_time); + + + +/* + mailimap_envelope is the list of fields that can be parsed by + the IMAP server. + + - date is the (non-parsed) content of the "Date" header field, + should be allocated with malloc() + + - subject is the subject of the message, should be allocated with + malloc() + + - sender is the the parsed content of the "Sender" field + + - reply-to is the parsed content of the "Reply-To" field + + - to is the parsed content of the "To" field + + - cc is the parsed content of the "Cc" field + + - bcc is the parsed content of the "Bcc" field + + - in_reply_to is the content of the "In-Reply-To" field, + should be allocated with malloc() + + - message_id is the content of the "Message-ID" field, + should be allocated with malloc() +*/ + +struct mailimap_envelope { + char * env_date; /* can be NULL */ + char * env_subject; /* can be NULL */ + struct mailimap_env_from * env_from; /* can be NULL */ + struct mailimap_env_sender * env_sender; /* can be NULL */ + struct mailimap_env_reply_to * env_reply_to; /* can be NULL */ + struct mailimap_env_to * env_to; /* can be NULL */ + struct mailimap_env_cc * env_cc; /* can be NULL */ + struct mailimap_env_bcc * env_bcc; /* can be NULL */ + char * env_in_reply_to; /* can be NULL */ + char * env_message_id; /* can be NULL */ +}; + +struct mailimap_envelope * +mailimap_envelope_new(char * env_date, char * env_subject, + struct mailimap_env_from * env_from, + struct mailimap_env_sender * env_sender, + struct mailimap_env_reply_to * env_reply_to, + struct mailimap_env_to * env_to, + struct mailimap_env_cc* env_cc, + struct mailimap_env_bcc * env_bcc, + char * env_in_reply_to, char * env_message_id); + +void mailimap_envelope_free(struct mailimap_envelope * env); + + + +/* + mailimap_env_bcc is the parsed "Bcc" field + + - list is the list of addresses +*/ + +struct mailimap_env_bcc { + clist * bcc_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_bcc * mailimap_env_bcc_new(clist * bcc_list); + +void mailimap_env_bcc_free(struct mailimap_env_bcc * env_bcc); + + +/* + mailimap_env_cc is the parsed "Cc" field + + - list is the list of addresses +*/ + +struct mailimap_env_cc { + clist * cc_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_cc * mailimap_env_cc_new(clist * cc_list); + +void mailimap_env_cc_free(struct mailimap_env_cc * env_cc); + + + +/* + mailimap_env_from is the parsed "From" field + + - list is the list of addresses +*/ + +struct mailimap_env_from { + clist * frm_list; /* list of (struct mailimap_address *) */ + /* != NULL */ +}; + +struct mailimap_env_from * mailimap_env_from_new(clist * frm_list); + +void mailimap_env_from_free(struct mailimap_env_from * env_from); + + + +/* + mailimap_env_reply_to is the parsed "Reply-To" field + + - list is the list of addresses +*/ + +struct mailimap_env_reply_to { + clist * rt_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_reply_to * mailimap_env_reply_to_new(clist * rt_list); + +void +mailimap_env_reply_to_free(struct mailimap_env_reply_to * env_reply_to); + + + +/* + mailimap_env_sender is the parsed "Sender" field + + - list is the list of addresses +*/ + +struct mailimap_env_sender { + clist * snd_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_sender * mailimap_env_sender_new(clist * snd_list); + +void mailimap_env_sender_free(struct mailimap_env_sender * env_sender); + + + +/* + mailimap_env_to is the parsed "To" field + + - list is the list of addresses +*/ + +struct mailimap_env_to { + clist * to_list; /* list of (struct mailimap_address *), != NULL */ +}; + +struct mailimap_env_to * mailimap_env_to_new(clist * to_list); + +void mailimap_env_to_free(struct mailimap_env_to * env_to); + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_ANSWERED, /* \Answered flag */ + MAILIMAP_FLAG_FLAGGED, /* \Flagged flag */ + MAILIMAP_FLAG_DELETED, /* \Deleted flag */ + MAILIMAP_FLAG_SEEN, /* \Seen flag */ + MAILIMAP_FLAG_DRAFT, /* \Draft flag */ + MAILIMAP_FLAG_KEYWORD, /* keyword flag */ + MAILIMAP_FLAG_EXTENSION /* \extension flag */ +}; + + +/* + mailimap_flag is a message flag (that we can associate with a message) + + - type is the type of the flag, MAILIMAP_FLAG_XXX + + - keyword is the flag when the flag is of keyword type, + should be allocated with malloc() + + - extension is the flag when the flag is of extension type, should be + allocated with malloc() +*/ + +struct mailimap_flag { + int fl_type; + union { + char * fl_keyword; /* can be NULL */ + char * fl_extension; /* can be NULL */ + } fl_data; +}; + +struct mailimap_flag * mailimap_flag_new(int fl_type, + char * fl_keyword, char * fl_extension); + +void mailimap_flag_free(struct mailimap_flag * f); + + + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_FETCH_ERROR, /* on parse error */ + MAILIMAP_FLAG_FETCH_RECENT, /* \Recent flag */ + MAILIMAP_FLAG_FETCH_OTHER /* other type of flag */ +}; + +/* + mailimap_flag_fetch is a message flag (when we fetch it) + + - type is the type of flag fetch + + - flag is the flag when this is not a \Recent flag +*/ + +struct mailimap_flag_fetch { + int fl_type; + struct mailimap_flag * fl_flag; /* can be NULL */ +}; + +struct mailimap_flag_fetch * +mailimap_flag_fetch_new(int fl_type, struct mailimap_flag * fl_flag); + +void mailimap_flag_fetch_free(struct mailimap_flag_fetch * flag_fetch); + + + + +/* this is the type of flag */ + +enum { + MAILIMAP_FLAG_PERM_ERROR, /* on parse error */ + MAILIMAP_FLAG_PERM_FLAG, /* to specify that usual flags can be changed */ + MAILIMAP_FLAG_PERM_ALL /* to specify that new flags can be created */ +}; + + +/* + mailimap_flag_perm is a flag returned in case of PERMANENTFLAGS response + + - type is the type of returned PERMANENTFLAGS, it can be + MAILIMAP_FLAG_PERM_FLAG (the given flag can be changed permanently) or + MAILIMAP_FLAG_PERM_ALL (new flags can be created) + + - flag is the given flag when type is MAILIMAP_FLAG_PERM_FLAG +*/ + +struct mailimap_flag_perm { + int fl_type; + struct mailimap_flag * fl_flag; /* can be NULL */ +}; + +struct mailimap_flag_perm * +mailimap_flag_perm_new(int fl_type, struct mailimap_flag * fl_flag); + +void mailimap_flag_perm_free(struct mailimap_flag_perm * flag_perm); + + +/* + mailimap_flag_list is a list of flags + + - list is a list of flags +*/ + +struct mailimap_flag_list { + clist * fl_list; /* list of (struct mailimap_flag *), != NULL */ +}; + +struct mailimap_flag_list * +mailimap_flag_list_new(clist * fl_list); + +void mailimap_flag_list_free(struct mailimap_flag_list * flag_list); + + + + +/* this is the type of greeting response */ + +enum { + MAILIMAP_GREETING_RESP_COND_ERROR, /* on parse error */ + MAILIMAP_GREETING_RESP_COND_AUTH, /* when connection is accepted */ + MAILIMAP_GREETING_RESP_COND_BYE /* when connection is refused */ +}; + +/* + mailimap_greeting is the response returned on connection + + - type is the type of response on connection, either + MAILIMAP_GREETING_RESP_COND_AUTH if connection is accepted or + MAIMIMAP_GREETING_RESP_COND_BYE if connection is refused +*/ + +struct mailimap_greeting { + int gr_type; + union { + struct mailimap_resp_cond_auth * gr_auth; /* can be NULL */ + struct mailimap_resp_cond_bye * gr_bye; /* can be NULL */ + } gr_data; +}; + +struct mailimap_greeting * +mailimap_greeting_new(int gr_type, + struct mailimap_resp_cond_auth * gr_auth, + struct mailimap_resp_cond_bye * gr_bye); + +void mailimap_greeting_free(struct mailimap_greeting * greeting); + + +/* + mailimap_header_list is a list of headers that can be specified when + we want to fetch fields + + - list is a list of header names, each header name should be allocated + with malloc() +*/ + +struct mailimap_header_list { + clist * hdr_list; /* list of astring (char *), != NULL */ +}; + +struct mailimap_header_list * +mailimap_header_list_new(clist * hdr_list); + +void +mailimap_header_list_free(struct mailimap_header_list * header_list); + + + +/* this is the type of mailbox STATUS that can be returned */ + +enum { + MAILIMAP_STATUS_ATT_MESSAGES, /* when requesting the number of + messages */ + MAILIMAP_STATUS_ATT_RECENT, /* when requesting the number of + recent messages */ + MAILIMAP_STATUS_ATT_UIDNEXT, /* when requesting the next unique + identifier */ + MAILIMAP_STATUS_ATT_UIDVALIDITY, /* when requesting the validity of + message unique identifiers*/ + MAILIMAP_STATUS_ATT_UNSEEN /* when requesting the number of + unseen messages */ +}; + +/* + mailimap_status_info is a returned information when a STATUS of + a mailbox is requested + + - att is the type of mailbox STATUS, the value can be + MAILIMAP_STATUS_ATT_MESSAGES, MAILIMAP_STATUS_ATT_RECENT, + MAILIMAP_STATUS_ATT_UIDNEXT, MAILIMAP_STATUS_ATT_UIDVALIDITY or + MAILIMAP_STATUS_ATT_UNSEEN + + - value is the value of the given information +*/ + +struct mailimap_status_info { + int st_att; + uint32_t st_value; +}; + +struct mailimap_status_info * +mailimap_status_info_new(int st_att, uint32_t st_value); + +void mailimap_status_info_free(struct mailimap_status_info * info); + + + +/* + mailimap_mailbox_data_status is the list of information returned + when a STATUS of a mailbox is requested + + - mailbox is the name of the mailbox, should be allocated with malloc() + + - status_info_list is the list of information returned +*/ + +struct mailimap_mailbox_data_status { + char * st_mailbox; + clist * st_info_list; /* list of (struct mailimap_status_info *) */ + /* can be NULL */ +}; + +struct mailimap_mailbox_data_status * +mailimap_mailbox_data_status_new(char * st_mailbox, + clist * st_info_list); + +void +mailimap_mailbox_data_status_free(struct mailimap_mailbox_data_status * info); + + + +/* this is the type of mailbox information that is returned */ + +enum { + MAILIMAP_MAILBOX_DATA_ERROR, /* on parse error */ + MAILIMAP_MAILBOX_DATA_FLAGS, /* flag that are applicable to the mailbox */ + MAILIMAP_MAILBOX_DATA_LIST, /* this is a mailbox in the list of mailboxes + returned on LIST command*/ + MAILIMAP_MAILBOX_DATA_LSUB, /* this is a mailbox in the list of + subscribed mailboxes returned on LSUB + command */ + MAILIMAP_MAILBOX_DATA_SEARCH, /* this is a list of messages numbers or + unique identifiers returned + on a SEARCH command*/ + MAILIMAP_MAILBOX_DATA_STATUS, /* this is the list of information returned + on a STATUS command */ + MAILIMAP_MAILBOX_DATA_EXISTS, /* this is the number of messages in the + mailbox */ + MAILIMAP_MAILBOX_DATA_RECENT, /* this is the number of recent messages + in the mailbox */ + MAILIMAP_MAILBOX_DATA_EXTENSION_DATA /* this mailbox-data stores data + returned by an extension */ +}; + +/* + mailimap_mailbox_data is an information related to a mailbox + + - type is the type of mailbox_data that is filled, the value of this field + can be MAILIMAP_MAILBOX_DATA_FLAGS, MAILIMAP_MAILBOX_DATA_LIST, + MAILIMAP_MAILBOX_DATA_LSUB, MAILIMAP_MAILBOX_DATA_SEARCH, + MAILIMAP_MAILBOX_DATA_STATUS, MAILIMAP_MAILBOX_DATA_EXISTS + or MAILIMAP_MAILBOX_DATA_RECENT. + + - flags is the flags that are applicable to the mailbox when + type is MAILIMAP_MAILBOX_DATA_FLAGS + + - list is a mailbox in the list of mailboxes returned on LIST command + when type is MAILIMAP_MAILBOX_DATA_LIST + + - lsub is a mailbox in the list of subscribed mailboxes returned on + LSUB command when type is MAILIMAP_MAILBOX_DATA_LSUB + + - search is a list of messages numbers or unique identifiers returned + on SEARCH command when type MAILIMAP_MAILBOX_DATA_SEARCH, each element + should be allocated with malloc() + + - status is a list of information returned on STATUS command when + type is MAILIMAP_MAILBOX_DATA_STATUS + + - exists is the number of messages in the mailbox when type + is MAILIMAP_MAILBOX_DATA_EXISTS + + - recent is the number of recent messages in the mailbox when type + is MAILIMAP_MAILBOX_DATA_RECENT +*/ + +struct mailimap_mailbox_data { + int mbd_type; + union { + struct mailimap_flag_list * mbd_flags; /* can be NULL */ + struct mailimap_mailbox_list * mbd_list; /* can be NULL */ + struct mailimap_mailbox_list * mbd_lsub; /* can be NULL */ + clist * mbd_search; /* list of nz-number (uint32_t *), can be NULL */ + struct mailimap_mailbox_data_status * mbd_status; /* can be NULL */ + uint32_t mbd_exists; + uint32_t mbd_recent; + struct mailimap_extension_data * mbd_extension; /* can be NULL */ + } mbd_data; +}; + +struct mailimap_mailbox_data * +mailimap_mailbox_data_new(int mbd_type, struct mailimap_flag_list * mbd_flags, + struct mailimap_mailbox_list * mbd_list, + struct mailimap_mailbox_list * mbd_lsub, + clist * mbd_search, + struct mailimap_mailbox_data_status * mbd_status, + uint32_t mbd_exists, + uint32_t mbd_recent, + struct mailimap_extension_data * mbd_extension); + +void +mailimap_mailbox_data_free(struct mailimap_mailbox_data * mb_data); + + + +/* this is the type of mailbox flags */ + +enum { + MAILIMAP_MBX_LIST_FLAGS_SFLAG, /* mailbox single flag - a flag in + {\NoSelect, \Marked, \Unmarked} */ + MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG /* mailbox other flag - mailbox flag + other than \NoSelect \Marked and + \Unmarked) */ +}; + +/* this is a single flag type */ + +enum { + MAILIMAP_MBX_LIST_SFLAG_ERROR, + MAILIMAP_MBX_LIST_SFLAG_MARKED, + MAILIMAP_MBX_LIST_SFLAG_NOSELECT, + MAILIMAP_MBX_LIST_SFLAG_UNMARKED +}; + +/* + mailimap_mbx_list_flags is a mailbox flag + + - type is the type of mailbox flag, it can be MAILIMAP_MBX_LIST_FLAGS_SFLAG, + or MAILIMAP_MBX_LIST_FLAGS_NO_SFLAG. + + - oflags is a list of "mailbox other flag" + + - sflag is a mailbox single flag +*/ + +struct mailimap_mbx_list_flags { + int mbf_type; + clist * mbf_oflags; /* list of + (struct mailimap_mbx_list_oflag *), != NULL */ + int mbf_sflag; +}; + +struct mailimap_mbx_list_flags * +mailimap_mbx_list_flags_new(int mbf_type, + clist * mbf_oflags, int mbf_sflag); + +void +mailimap_mbx_list_flags_free(struct mailimap_mbx_list_flags * mbx_list_flags); + + + +/* this is the type of the mailbox other flag */ + +enum { + MAILIMAP_MBX_LIST_OFLAG_ERROR, /* on parse error */ + MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS, /* \NoInferior flag */ + MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT /* other flag */ +}; + +/* + mailimap_mbx_list_oflag is a mailbox other flag + + - type can be MAILIMAP_MBX_LIST_OFLAG_NOINFERIORS when this is + a \NoInferior flag or MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT + + - flag_ext is set when MAILIMAP_MBX_LIST_OFLAG_FLAG_EXT and is + an extension flag, should be allocated with malloc() +*/ + +struct mailimap_mbx_list_oflag { + int of_type; + char * of_flag_ext; /* can be NULL */ +}; + +struct mailimap_mbx_list_oflag * +mailimap_mbx_list_oflag_new(int of_type, char * of_flag_ext); + +void +mailimap_mbx_list_oflag_free(struct mailimap_mbx_list_oflag * oflag); + + + +/* + mailimap_mailbox_list is a list of mailbox flags + + - mb_flag is a list of mailbox flags + + - delimiter is the delimiter of the mailbox path + + - mb is the name of the mailbox, should be allocated with malloc() +*/ + +struct mailimap_mailbox_list { + struct mailimap_mbx_list_flags * mb_flag; /* can be NULL */ + char mb_delimiter; + char * mb_name; /* != NULL */ +}; + +struct mailimap_mailbox_list * +mailimap_mailbox_list_new(struct mailimap_mbx_list_flags * mbx_flags, + char mb_delimiter, char * mb_name); + +void +mailimap_mailbox_list_free(struct mailimap_mailbox_list * mb_list); + + + +/* this is the MIME type */ + +enum { + MAILIMAP_MEDIA_BASIC_APPLICATION, /* application/xxx */ + MAILIMAP_MEDIA_BASIC_AUDIO, /* audio/xxx */ + MAILIMAP_MEDIA_BASIC_IMAGE, /* image/xxx */ + MAILIMAP_MEDIA_BASIC_MESSAGE, /* message/xxx */ + MAILIMAP_MEDIA_BASIC_VIDEO, /* video/xxx */ + MAILIMAP_MEDIA_BASIC_OTHER /* for all other cases */ +}; + + +/* + mailimap_media_basic is the MIME type + + - type can be MAILIMAP_MEDIA_BASIC_APPLICATION, MAILIMAP_MEDIA_BASIC_AUDIO, + MAILIMAP_MEDIA_BASIC_IMAGE, MAILIMAP_MEDIA_BASIC_MESSAGE, + MAILIMAP_MEDIA_BASIC_VIDEO or MAILIMAP_MEDIA_BASIC_OTHER + + - basic_type is defined when type is MAILIMAP_MEDIA_BASIC_OTHER, should + be allocated with malloc() + + - subtype is the subtype of the MIME type, for example, this is + "data" in "application/data", should be allocated with malloc() +*/ + +struct mailimap_media_basic { + int med_type; + char * med_basic_type; /* can be NULL */ + char * med_subtype; /* != NULL */ +}; + +struct mailimap_media_basic * +mailimap_media_basic_new(int med_type, + char * med_basic_type, char * med_subtype); + +void +mailimap_media_basic_free(struct mailimap_media_basic * media_basic); + + + +/* this is the type of message data */ + +enum { + MAILIMAP_MESSAGE_DATA_ERROR, + MAILIMAP_MESSAGE_DATA_EXPUNGE, + MAILIMAP_MESSAGE_DATA_FETCH +}; + +/* + mailimap_message_data is an information related to a message + + - number is the number or the unique identifier of the message + + - type is the type of information, this value can be + MAILIMAP_MESSAGE_DATA_EXPUNGE or MAILIMAP_MESSAGE_DATA_FETCH + + - msg_att is the message data +*/ + +struct mailimap_message_data { + uint32_t mdt_number; + int mdt_type; + struct mailimap_msg_att * mdt_msg_att; /* can be NULL */ + /* if type = EXPUNGE, can be NULL */ +}; + +struct mailimap_message_data * +mailimap_message_data_new(uint32_t mdt_number, int mdt_type, + struct mailimap_msg_att * mdt_msg_att); + +void +mailimap_message_data_free(struct mailimap_message_data * msg_data); + + + +/* this the type of the message attributes */ + +enum { + MAILIMAP_MSG_ATT_ITEM_ERROR, /* on parse error */ + MAILIMAP_MSG_ATT_ITEM_DYNAMIC, /* dynamic message attributes (flags) */ + MAILIMAP_MSG_ATT_ITEM_STATIC /* static messages attributes + (message content) */ +}; + +/* + mailimap_msg_att_item is a message attribute + + - type is the type of message attribute, the value can be + MAILIMAP_MSG_ATT_ITEM_DYNAMIC or MAILIMAP_MSG_ATT_ITEM_STATIC + + - msg_att_dyn is a dynamic message attribute when type is + MAILIMAP_MSG_ATT_ITEM_DYNAMIC + + - msg_att_static is a static message attribute when type is + MAILIMAP_MSG_ATT_ITEM_STATIC +*/ + +struct mailimap_msg_att_item { + int att_type; + union { + struct mailimap_msg_att_dynamic * att_dyn; /* can be NULL */ + struct mailimap_msg_att_static * att_static; /* can be NULL */ + } att_data; +}; + +struct mailimap_msg_att_item * +mailimap_msg_att_item_new(int att_type, + struct mailimap_msg_att_dynamic * att_dyn, + struct mailimap_msg_att_static * att_static); + +void +mailimap_msg_att_item_free(struct mailimap_msg_att_item * item); + + +/* + mailimap_msg_att is a list of attributes + + - list is a list of message attributes + + - number is the message number or unique identifier, this field + has been added for implementation purpose +*/ + +struct mailimap_msg_att { + clist * att_list; /* list of (struct mailimap_msg_att_item *) */ + /* != NULL */ + uint32_t att_number; /* extra field to store the message number, + used for mailimap */ +}; + +struct mailimap_msg_att * mailimap_msg_att_new(clist * att_list); + +void mailimap_msg_att_free(struct mailimap_msg_att * msg_att); + + +/* + mailimap_msg_att_dynamic is a dynamic message attribute + + - list is a list of flags (that have been fetched) +*/ + +struct mailimap_msg_att_dynamic { + clist * att_list; /* list of (struct mailimap_flag_fetch *) */ + /* can be NULL */ +}; + +struct mailimap_msg_att_dynamic * +mailimap_msg_att_dynamic_new(clist * att_list); + +void +mailimap_msg_att_dynamic_free(struct mailimap_msg_att_dynamic * msg_att_dyn); + + + +/* + mailimap_msg_att_body_section is a MIME part content + + - section is the location of the MIME part in the message + + - origin_octet is the offset of the requested part of the MIME part + + - body_part is the content or partial content of the MIME part, + should be allocated through a MMAPString + + - length is the size of the content +*/ + +struct mailimap_msg_att_body_section { + struct mailimap_section * sec_section; /* != NULL */ + uint32_t sec_origin_octet; + char * sec_body_part; /* can be NULL */ + size_t sec_length; +}; + +struct mailimap_msg_att_body_section * +mailimap_msg_att_body_section_new(struct mailimap_section * section, + uint32_t sec_origin_octet, + char * sec_body_part, + size_t sec_length); + +void +mailimap_msg_att_body_section_free(struct mailimap_msg_att_body_section * + msg_att_body_section); + + + +/* + this is the type of static message attribute +*/ + +enum { + MAILIMAP_MSG_ATT_ERROR, /* on parse error */ + MAILIMAP_MSG_ATT_ENVELOPE, /* this is the fields that can be + parsed by the server */ + MAILIMAP_MSG_ATT_INTERNALDATE, /* this is the message date kept + by the server */ + MAILIMAP_MSG_ATT_RFC822, /* this is the message content + (header and body) */ + MAILIMAP_MSG_ATT_RFC822_HEADER, /* this is the message header */ + MAILIMAP_MSG_ATT_RFC822_TEXT, /* this is the message text part */ + MAILIMAP_MSG_ATT_RFC822_SIZE, /* this is the size of the message content */ + MAILIMAP_MSG_ATT_BODY, /* this is the MIME description of + the message */ + MAILIMAP_MSG_ATT_BODYSTRUCTURE, /* this is the MIME description of the + message with additional information */ + MAILIMAP_MSG_ATT_BODY_SECTION, /* this is a MIME part content */ + MAILIMAP_MSG_ATT_UID /* this is the message unique identifier */ +}; + +/* + mailimap_msg_att_static is a given part of the message + + - type is the type of the static message attribute, the value can be + MAILIMAP_MSG_ATT_ENVELOPE, MAILIMAP_MSG_ATT_INTERNALDATE, + MAILIMAP_MSG_ATT_RFC822, MAILIMAP_MSG_ATT_RFC822_HEADER, + MAILIMAP_MSG_ATT_RFC822_TEXT, MAILIMAP_MSG_ATT_RFC822_SIZE, + MAILIMAP_MSG_ATT_BODY, MAILIMAP_MSG_ATT_BODYSTRUCTURE, + MAILIMAP_MSG_ATT_BODY_SECTION, MAILIMAP_MSG_ATT_UID + + - env is the headers parsed by the server if type is + MAILIMAP_MSG_ATT_ENVELOPE + + - internal_date is the date of message kept by the server if type is + MAILIMAP_MSG_ATT_INTERNALDATE + + - rfc822 is the message content if type is MAILIMAP_MSG_ATT_RFC822, + should be allocated through a MMAPString + + - rfc822_header is the message header if type is + MAILIMAP_MSG_ATT_RFC822_HEADER, should be allocated through a MMAPString + + - rfc822_text is the message text part if type is + MAILIMAP_MSG_ATT_RFC822_TEXT, should be allocated through a MMAPString + + - rfc822_size is the message size if type is MAILIMAP_MSG_ATT_SIZE + + - body is the MIME description of the message + + - bodystructure is the MIME description of the message with additional + information + + - body_section is a MIME part content + + - uid is a unique message identifier +*/ + +struct mailimap_msg_att_static { + int att_type; + union { + struct mailimap_envelope * att_env; /* can be NULL */ + struct mailimap_date_time * att_internal_date; /* can be NULL */ + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822; + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822_header; + struct { + char * att_content; /* can be NULL */ + size_t att_length; + } att_rfc822_text; + uint32_t att_rfc822_size; + struct mailimap_body * att_bodystructure; /* can be NULL */ + struct mailimap_body * att_body; /* can be NULL */ + struct mailimap_msg_att_body_section * att_body_section; /* can be NULL */ + uint32_t att_uid; + } att_data; +}; + +struct mailimap_msg_att_static * +mailimap_msg_att_static_new(int att_type, struct mailimap_envelope * att_env, + struct mailimap_date_time * att_internal_date, + char * att_rfc822, + char * att_rfc822_header, + char * att_rfc822_text, + size_t att_length, + uint32_t att_rfc822_size, + struct mailimap_body * att_bodystructure, + struct mailimap_body * att_body, + struct mailimap_msg_att_body_section * att_body_section, + uint32_t att_uid); + +void +mailimap_msg_att_static_free(struct mailimap_msg_att_static * item); + + + +/* this is the type of a response element */ + +enum { + MAILIMAP_RESP_ERROR, /* on parse error */ + MAILIMAP_RESP_CONT_REQ, /* continuation request */ + MAILIMAP_RESP_RESP_DATA /* response data */ +}; + +/* + mailimap_cont_req_or_resp_data is a response element + + - type is the type of response, the value can be MAILIMAP_RESP_CONT_REQ + or MAILIMAP_RESP_RESP_DATA + + - cont_req is a continuation request + + - resp_data is a reponse data +*/ + +struct mailimap_cont_req_or_resp_data { + int rsp_type; + union { + struct mailimap_continue_req * rsp_cont_req; /* can be NULL */ + struct mailimap_response_data * rsp_resp_data; /* can be NULL */ + } rsp_data; +}; + +struct mailimap_cont_req_or_resp_data * +mailimap_cont_req_or_resp_data_new(int rsp_type, + struct mailimap_continue_req * rsp_cont_req, + struct mailimap_response_data * rsp_resp_data); + +void +mailimap_cont_req_or_resp_data_free(struct mailimap_cont_req_or_resp_data * + cont_req_or_resp_data); + + +/* + mailimap_response is a list of response elements + + - cont_req_or_resp_data_list is a list of response elements + + - resp_done is an ending response element +*/ + +struct mailimap_response { + clist * rsp_cont_req_or_resp_data_list; + /* list of (struct mailiap_cont_req_or_resp_data *) */ + /* can be NULL */ + struct mailimap_response_done * rsp_resp_done; /* != NULL */ +}; + +struct mailimap_response * +mailimap_response_new(clist * rsp_cont_req_or_resp_data_list, + struct mailimap_response_done * rsp_resp_done); + +void +mailimap_response_free(struct mailimap_response * resp); + + + +/* this is the type of an untagged response */ + +enum { + MAILIMAP_RESP_DATA_TYPE_ERROR, /* on parse error */ + MAILIMAP_RESP_DATA_TYPE_COND_STATE, /* condition state response */ + MAILIMAP_RESP_DATA_TYPE_COND_BYE, /* BYE response (server is about + to close the connection) */ + MAILIMAP_RESP_DATA_TYPE_MAILBOX_DATA, /* response related to a mailbox */ + MAILIMAP_RESP_DATA_TYPE_MESSAGE_DATA, /* response related to a message */ + MAILIMAP_RESP_DATA_TYPE_CAPABILITY_DATA, /* capability information */ + MAILIMAP_RESP_DATA_TYPE_EXTENSION_DATA /* data parsed by extension */ +}; + +/* + mailimap_reponse_data is an untagged response + + - type is the type of the untagged response, it can be + MAILIMAP_RESP_DATA_COND_STATE, MAILIMAP_RESP_DATA_COND_BYE, + MAILIMAP_RESP_DATA_MAILBOX_DATA, MAILIMAP_RESP_DATA_MESSAGE_DATA + or MAILIMAP_RESP_DATA_CAPABILITY_DATA + + - cond_state is a condition state response + + - bye is a BYE response (server is about to close the connection) + + - mailbox_data is a response related to a mailbox + + - message_data is a response related to a message + + - capability is information about capabilities +*/ + +struct mailimap_response_data { + int rsp_type; + union { + struct mailimap_resp_cond_state * rsp_cond_state; /* can be NULL */ + struct mailimap_resp_cond_bye * rsp_bye; /* can be NULL */ + struct mailimap_mailbox_data * rsp_mailbox_data; /* can be NULL */ + struct mailimap_message_data * rsp_message_data; /* can be NULL */ + struct mailimap_capability_data * rsp_capability_data; /* can be NULL */ + struct mailimap_extension_data * rsp_extension_data; /* can be NULL */ + } rsp_data; +}; + +struct mailimap_response_data * +mailimap_response_data_new(int rsp_type, + struct mailimap_resp_cond_state * rsp_cond_state, + struct mailimap_resp_cond_bye * rsp_bye, + struct mailimap_mailbox_data * rsp_mailbox_data, + struct mailimap_message_data * rsp_message_data, + struct mailimap_capability_data * rsp_capability_data, + struct mailimap_extension_data * rsp_extension_data); + +void +mailimap_response_data_free(struct mailimap_response_data * resp_data); + + + +/* this is the type of an ending response */ + +enum { + MAILIMAP_RESP_DONE_TYPE_ERROR, /* on parse error */ + MAILIMAP_RESP_DONE_TYPE_TAGGED, /* tagged response */ + MAILIMAP_RESP_DONE_TYPE_FATAL /* fatal error response */ +}; + +/* + mailimap_response_done is an ending response + + - type is the type of the ending response + + - tagged is a tagged response + + - fatal is a fatal error response +*/ + +struct mailimap_response_done { + int rsp_type; + union { + struct mailimap_response_tagged * rsp_tagged; /* can be NULL */ + struct mailimap_response_fatal * rsp_fatal; /* can be NULL */ + } rsp_data; +}; + +struct mailimap_response_done * +mailimap_response_done_new(int rsp_type, + struct mailimap_response_tagged * rsp_tagged, + struct mailimap_response_fatal * rsp_fatal); + +void mailimap_response_done_free(struct mailimap_response_done * + resp_done); + + +/* + mailimap_response_fatal is a fatal error response + + - bye is a BYE response text +*/ + +struct mailimap_response_fatal { + struct mailimap_resp_cond_bye * rsp_bye; /* != NULL */ +}; + +struct mailimap_response_fatal * +mailimap_response_fatal_new(struct mailimap_resp_cond_bye * rsp_bye); + +void mailimap_response_fatal_free(struct mailimap_response_fatal * resp_fatal); + + + +/* + mailimap_response_tagged is a tagged response + + - tag is the sent tag, should be allocated with malloc() + + - cond_state is a condition state response +*/ + +struct mailimap_response_tagged { + char * rsp_tag; /* != NULL */ + struct mailimap_resp_cond_state * rsp_cond_state; /* != NULL */ +}; + +struct mailimap_response_tagged * +mailimap_response_tagged_new(char * rsp_tag, + struct mailimap_resp_cond_state * rsp_cond_state); + +void +mailimap_response_tagged_free(struct mailimap_response_tagged * tagged); + + +/* this is the type of an authentication condition response */ + +enum { + MAILIMAP_RESP_COND_AUTH_ERROR, /* on parse error */ + MAILIMAP_RESP_COND_AUTH_OK, /* authentication is needed */ + MAILIMAP_RESP_COND_AUTH_PREAUTH /* authentication is not needed */ +}; + +/* + mailimap_resp_cond_auth is an authentication condition response + + - type is the type of the authentication condition response, + the value can be MAILIMAP_RESP_COND_AUTH_OK or + MAILIMAP_RESP_COND_AUTH_PREAUTH + + - text is a text response +*/ + +struct mailimap_resp_cond_auth { + int rsp_type; + struct mailimap_resp_text * rsp_text; /* != NULL */ +}; + +struct mailimap_resp_cond_auth * +mailimap_resp_cond_auth_new(int rsp_type, + struct mailimap_resp_text * rsp_text); + +void +mailimap_resp_cond_auth_free(struct mailimap_resp_cond_auth * cond_auth); + + + +/* + mailimap_resp_cond_bye is a BYE response + + - text is a text response +*/ + +struct mailimap_resp_cond_bye { + struct mailimap_resp_text * rsp_text; /* != NULL */ +}; + +struct mailimap_resp_cond_bye * +mailimap_resp_cond_bye_new(struct mailimap_resp_text * rsp_text); + +void +mailimap_resp_cond_bye_free(struct mailimap_resp_cond_bye * cond_bye); + + + +/* this is the type of a condition state response */ + +enum { + MAILIMAP_RESP_COND_STATE_OK, + MAILIMAP_RESP_COND_STATE_NO, + MAILIMAP_RESP_COND_STATE_BAD +}; + +/* + mailimap_resp_cond_state is a condition state reponse + + - type is the type of the condition state response + + - text is a text response +*/ + +struct mailimap_resp_cond_state { + int rsp_type; + struct mailimap_resp_text * rsp_text; /* can be NULL */ +}; + +struct mailimap_resp_cond_state * +mailimap_resp_cond_state_new(int rsp_type, + struct mailimap_resp_text * rsp_text); + +void +mailimap_resp_cond_state_free(struct mailimap_resp_cond_state * cond_state); + + + +/* + mailimap_resp_text is a text response + + - resp_code is a response code + + - text is a human readable text, should be allocated with malloc() +*/ + +struct mailimap_resp_text { + struct mailimap_resp_text_code * rsp_code; /* can be NULL */ + char * rsp_text; /* can be NULL */ +}; + +struct mailimap_resp_text * +mailimap_resp_text_new(struct mailimap_resp_text_code * resp_code, + char * rsp_text); + +void mailimap_resp_text_free(struct mailimap_resp_text * resp_text); + + + +/* this is the type of the response code */ + +enum { + MAILIMAP_RESP_TEXT_CODE_ALERT, /* ALERT response */ + MAILIMAP_RESP_TEXT_CODE_BADCHARSET, /* BADCHARSET response */ + MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, /* CAPABILITY response */ + MAILIMAP_RESP_TEXT_CODE_PARSE, /* PARSE response */ + MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, /* PERMANENTFLAGS response */ + MAILIMAP_RESP_TEXT_CODE_READ_ONLY, /* READONLY response */ + MAILIMAP_RESP_TEXT_CODE_READ_WRITE, /* READWRITE response */ + MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, /* TRYCREATE response */ + MAILIMAP_RESP_TEXT_CODE_UIDNEXT, /* UIDNEXT response */ + MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, /* UIDVALIDITY response */ + MAILIMAP_RESP_TEXT_CODE_UNSEEN, /* UNSEEN response */ + MAILIMAP_RESP_TEXT_CODE_OTHER, /* other type of response */ + MAILIMAP_RESP_TEXT_CODE_EXTENSION /* extension response */ +}; + +/* + mailimap_resp_text_code is a response code + + - type is the type of the response code, the value can be + MAILIMAP_RESP_TEXT_CODE_ALERT, MAILIMAP_RESP_TEXT_CODE_BADCHARSET, + MAILIMAP_RESP_TEXT_CODE_CAPABILITY_DATA, MAILIMAP_RESP_TEXT_CODE_PARSE, + MAILIMAP_RESP_TEXT_CODE_PERMANENTFLAGS, MAILIMAP_RESP_TEXT_CODE_READ_ONLY, + MAILIMAP_RESP_TEXT_CODE_READ_WRITE, MAILIMAP_RESP_TEXT_CODE_TRY_CREATE, + MAILIMAP_RESP_TEXT_CODE_UIDNEXT, MAILIMAP_RESP_TEXT_CODE_UIDVALIDITY, + MAILIMAP_RESP_TEXT_CODE_UNSEEN or MAILIMAP_RESP_TEXT_CODE_OTHER + + - badcharset is a list of charsets if type + is MAILIMAP_RESP_TEXT_CODE_BADCHARSET, each element should be + allocated with malloc() + + - cap_data is a list of capabilities + + - perm_flags is a list of flags, this is the flags that can be changed + permanently on the messages of the mailbox. + + - uidnext is the next unique identifier of a message + + - uidvalidity is the unique identifier validity value + + - first_unseen is the number of the first message without the \Seen flag + + - atom is a keyword for an extension response code, should be allocated + with malloc() + + - atom_value is the data related with the extension response code, + should be allocated with malloc() +*/ + +struct mailimap_resp_text_code { + int rc_type; + union { + clist * rc_badcharset; /* list of astring (char *) */ + /* can be NULL */ + struct mailimap_capability_data * rc_cap_data; /* != NULL */ + clist * rc_perm_flags; /* list of (struct mailimap_flag_perm *) */ + /* can be NULL */ + uint32_t rc_uidnext; + uint32_t rc_uidvalidity; + uint32_t rc_first_unseen; + struct { + char * atom_name; /* can be NULL */ + char * atom_value; /* can be NULL */ + } rc_atom; + struct mailimap_extension_data * rc_ext_data; /* can be NULL */ + } rc_data; +}; + +struct mailimap_resp_text_code * +mailimap_resp_text_code_new(int rc_type, clist * rc_badcharset, + struct mailimap_capability_data * rc_cap_data, + clist * rc_perm_flags, + uint32_t rc_uidnext, uint32_t rc_uidvalidity, + uint32_t rc_first_unseen, char * rc_atom, char * rc_atom_value, + struct mailimap_extension_data * rc_ext_data); + +void +mailimap_resp_text_code_free(struct mailimap_resp_text_code * resp_text_code); + + +/* + mailimap_section is a MIME part section identifier + + section_spec is the MIME section identifier +*/ + +struct mailimap_section { + struct mailimap_section_spec * sec_spec; /* can be NULL */ +}; + +struct mailimap_section * +mailimap_section_new(struct mailimap_section_spec * sec_spec); + +void mailimap_section_free(struct mailimap_section * section); + + +/* this is the type of the message/rfc822 part description */ + +enum { + MAILIMAP_SECTION_MSGTEXT_HEADER, /* header fields part of the + message */ + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, /* given header fields of the + message */ + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, /* header fields of the + message except the given */ + MAILIMAP_SECTION_MSGTEXT_TEXT /* text part */ +}; + +/* + mailimap_section_msgtext is a message/rfc822 part description + + - type is the type of the content part and the value can be + MAILIMAP_SECTION_MSGTEXT_HEADER, MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT + or MAILIMAP_SECTION_MSGTEXT_TEXT + + - header_list is the list of headers when type is + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS or + MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT +*/ + +struct mailimap_section_msgtext { + int sec_type; + struct mailimap_header_list * sec_header_list; /* can be NULL */ +}; + +struct mailimap_section_msgtext * +mailimap_section_msgtext_new(int sec_type, + struct mailimap_header_list * sec_header_list); + +void +mailimap_section_msgtext_free(struct mailimap_section_msgtext * msgtext); + + + +/* + mailimap_section_part is the MIME part location in a message + + - section_id is a list of number index of the sub-part in the mail structure, + each element should be allocated with malloc() + +*/ + +struct mailimap_section_part { + clist * sec_id; /* list of nz-number (uint32_t *) */ + /* != NULL */ +}; + +struct mailimap_section_part * +mailimap_section_part_new(clist * sec_id); + +void +mailimap_section_part_free(struct mailimap_section_part * section_part); + + + +/* this is the type of section specification */ + +enum { + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT, /* if requesting data of the root + MIME message/rfc822 part */ + MAILIMAP_SECTION_SPEC_SECTION_PART /* location of the MIME part + in the message */ +}; + +/* + mailimap_section_spec is a section specification + + - type is the type of the section specification, the value can be + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT or + MAILIMAP_SECTION_SPEC_SECTION_PART + + - section_msgtext is a message/rfc822 part description if type is + MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT + + - section_part is a body part location in the message if type is + MAILIMAP_SECTION_SPEC_SECTION_PART + + - section_text is a body part location for a given MIME part, + this can be NULL if the body of the part is requested (and not + the MIME header). +*/ + +struct mailimap_section_spec { + int sec_type; + union { + struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */ + struct mailimap_section_part * sec_part; /* can be NULL */ + } sec_data; + struct mailimap_section_text * sec_text; /* can be NULL */ +}; + +struct mailimap_section_spec * +mailimap_section_spec_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext, + struct mailimap_section_part * sec_part, + struct mailimap_section_text * sec_text); + +void +mailimap_section_spec_free(struct mailimap_section_spec * section_spec); + + + +/* this is the type of body part location for a given MIME part */ + +enum { + MAILIMAP_SECTION_TEXT_ERROR, /* on parse error **/ + MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT, /* if the MIME type is + message/rfc822, headers or text + can be requested */ + MAILIMAP_SECTION_TEXT_MIME /* for all MIME types, + MIME headers can be requested */ +}; + +/* + mailimap_section_text is the body part location for a given MIME part + + - type can be MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT or + MAILIMAP_SECTION_TEXT_MIME + + - section_msgtext is the part of the MIME part when MIME type is + message/rfc822 than can be requested, when type is + MAILIMAP_TEXT_SECTION_MSGTEXT +*/ + +struct mailimap_section_text { + int sec_type; + struct mailimap_section_msgtext * sec_msgtext; /* can be NULL */ +}; + +struct mailimap_section_text * +mailimap_section_text_new(int sec_type, + struct mailimap_section_msgtext * sec_msgtext); + +void +mailimap_section_text_free(struct mailimap_section_text * section_text); + + + + + + + + + + +/* ************************************************************************* */ +/* the following part concerns only the IMAP command that are sent */ + + +/* + mailimap_set_item is a message set + + - first is the first message of the set + - last is the last message of the set + + this can be message numbers of message unique identifiers +*/ + +struct mailimap_set_item { + uint32_t set_first; + uint32_t set_last; +}; + +struct mailimap_set_item * +mailimap_set_item_new(uint32_t set_first, uint32_t set_last); + +void mailimap_set_item_free(struct mailimap_set_item * set_item); + + + +/* + set is a list of message sets + + - list is a list of message sets +*/ + +struct mailimap_set { + clist * set_list; /* list of (struct mailimap_set_item *) */ +}; + +struct mailimap_set * mailimap_set_new(clist * list); + +void mailimap_set_free(struct mailimap_set * set); + + +/* + mailimap_date is a date + + - day is the day in the month (1 to 31) + + - month (1 to 12) + + - year (4 digits) +*/ + +struct mailimap_date { + int dt_day; + int dt_month; + int dt_year; +}; + +struct mailimap_date * +mailimap_date_new(int dt_day, int dt_month, int dt_year); + +void mailimap_date_free(struct mailimap_date * date); + + + + +/* this is the type of fetch attribute for a given message */ + +enum { + MAILIMAP_FETCH_ATT_ENVELOPE, /* to fetch the headers parsed by + the IMAP server */ + MAILIMAP_FETCH_ATT_FLAGS, /* to fetch the flags */ + MAILIMAP_FETCH_ATT_INTERNALDATE, /* to fetch the date of the message + kept by the server */ + MAILIMAP_FETCH_ATT_RFC822, /* to fetch the entire message */ + MAILIMAP_FETCH_ATT_RFC822_HEADER, /* to fetch the headers */ + MAILIMAP_FETCH_ATT_RFC822_SIZE, /* to fetch the size */ + MAILIMAP_FETCH_ATT_RFC822_TEXT, /* to fetch the text part */ + MAILIMAP_FETCH_ATT_BODY, /* to fetch the MIME structure */ + MAILIMAP_FETCH_ATT_BODYSTRUCTURE, /* to fetch the MIME structure with + additional information */ + MAILIMAP_FETCH_ATT_UID, /* to fetch the unique identifier */ + MAILIMAP_FETCH_ATT_BODY_SECTION, /* to fetch a given part */ + MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION /* to fetch a given part without + marking the message as read */ +}; + + +/* + mailimap_fetch_att is the description of the fetch attribute + + - type is the type of fetch attribute, the value can be + MAILIMAP_FETCH_ATT_ENVELOPE, MAILIMAP_FETCH_ATT_FLAGS, + MAILIMAP_FETCH_ATT_INTERNALDATE, MAILIMAP_FETCH_ATT_RFC822, + MAILIMAP_FETCH_ATT_RFC822_HEADER, MAILIMAP_FETCH_ATT_RFC822_SIZE, + MAILIMAP_FETCH_ATT_RFC822_TEXT, MAILIMAP_FETCH_ATT_BODY, + MAILIMAP_FETCH_ATT_BODYSTRUCTURE, MAILIMAP_FETCH_ATT_UID, + MAILIMAP_FETCH_ATT_BODY_SECTION or MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION + + - section is the location of the part to fetch if type is + MAILIMAP_FETCH_ATT_BODY_SECTION or MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION + + - offset is the first byte to fetch in the given part + + - size is the maximum size of the part to fetch +*/ + +struct mailimap_fetch_att { + int att_type; + struct mailimap_section * att_section; + uint32_t att_offset; + uint32_t att_size; +}; + +struct mailimap_fetch_att * +mailimap_fetch_att_new(int att_type, struct mailimap_section * att_section, + uint32_t att_offset, uint32_t att_size); + + +void mailimap_fetch_att_free(struct mailimap_fetch_att * fetch_att); + + +/* this is the type of a FETCH operation */ + +enum { + MAILIMAP_FETCH_TYPE_ALL, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE ENVELOPE) */ + MAILIMAP_FETCH_TYPE_FULL, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE ENVELOPE BODY) */ + MAILIMAP_FETCH_TYPE_FAST, /* equivalent to (FLAGS INTERNALDATE + RFC822.SIZE) */ + MAILIMAP_FETCH_TYPE_FETCH_ATT, /* when there is only of fetch + attribute */ + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST /* when there is a list of fetch + attributes */ +}; + +/* + mailimap_fetch_type is the description of the FETCH operation + + - type can be MAILIMAP_FETCH_TYPE_ALL, MAILIMAP_FETCH_TYPE_FULL, + MAILIMAP_FETCH_TYPE_FAST, MAILIMAP_FETCH_TYPE_FETCH_ATT or + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST + + - fetch_att is a fetch attribute if type is MAILIMAP_FETCH_TYPE_FETCH_ATT + + - fetch_att_list is a list of fetch attributes if type is + MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST +*/ + +struct mailimap_fetch_type { + int ft_type; + union { + struct mailimap_fetch_att * ft_fetch_att; + clist * ft_fetch_att_list; /* list of (struct mailimap_fetch_att *) */ + } ft_data; +}; + +struct mailimap_fetch_type * +mailimap_fetch_type_new(int ft_type, + struct mailimap_fetch_att * ft_fetch_att, + clist * ft_fetch_att_list); + + +void mailimap_fetch_type_free(struct mailimap_fetch_type * fetch_type); + + + +/* + mailimap_store_att_flags is the description of the STORE operation + (change flags of a message) + + - sign can be 0 (set flag), +1 (add flag) or -1 (remove flag) + + - silent has a value of 1 if the flags are changed with no server + response + + - flag_list is the list of flags to change +*/ + +struct mailimap_store_att_flags { + int fl_sign; + int fl_silent; + struct mailimap_flag_list * fl_flag_list; +}; + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new(int fl_sign, int fl_silent, + struct mailimap_flag_list * fl_flag_list); + +void mailimap_store_att_flags_free(struct mailimap_store_att_flags * + store_att_flags); + + + +/* this is the condition of the SEARCH operation */ + +enum { + MAILIMAP_SEARCH_KEY_ALL, /* all messages */ + MAILIMAP_SEARCH_KEY_ANSWERED, /* messages with the flag \Answered */ + MAILIMAP_SEARCH_KEY_BCC, /* messages whose Bcc field contains the + given string */ + MAILIMAP_SEARCH_KEY_BEFORE, /* messages whose internal date is earlier + than the specified date */ + MAILIMAP_SEARCH_KEY_BODY, /* message that contains the given string + (in header and text parts) */ + MAILIMAP_SEARCH_KEY_CC, /* messages whose Cc field contains the + given string */ + MAILIMAP_SEARCH_KEY_DELETED, /* messages with the flag \Deleted */ + MAILIMAP_SEARCH_KEY_FLAGGED, /* messages with the flag \Flagged */ + MAILIMAP_SEARCH_KEY_FROM, /* messages whose From field contains the + given string */ + MAILIMAP_SEARCH_KEY_KEYWORD, /* messages with the flag keyword set */ + MAILIMAP_SEARCH_KEY_NEW, /* messages with the flag \Recent and not + the \Seen flag */ + MAILIMAP_SEARCH_KEY_OLD, /* messages that do not have the + \Recent flag set */ + MAILIMAP_SEARCH_KEY_ON, /* messages whose internal date is the + specified date */ + MAILIMAP_SEARCH_KEY_RECENT, /* messages with the flag \Recent */ + MAILIMAP_SEARCH_KEY_SEEN, /* messages with the flag \Seen */ + MAILIMAP_SEARCH_KEY_SINCE, /* messages whose internal date is later + than specified date */ + MAILIMAP_SEARCH_KEY_SUBJECT, /* messages whose Subject field contains the + given string */ + MAILIMAP_SEARCH_KEY_TEXT, /* messages whose text part contains the + given string */ + MAILIMAP_SEARCH_KEY_TO, /* messages whose To field contains the + given string */ + MAILIMAP_SEARCH_KEY_UNANSWERED, /* messages with no flag \Answered */ + MAILIMAP_SEARCH_KEY_UNDELETED, /* messages with no flag \Deleted */ + MAILIMAP_SEARCH_KEY_UNFLAGGED, /* messages with no flag \Flagged */ + MAILIMAP_SEARCH_KEY_UNKEYWORD, /* messages with no flag keyword */ + MAILIMAP_SEARCH_KEY_UNSEEN, /* messages with no flag \Seen */ + MAILIMAP_SEARCH_KEY_DRAFT, /* messages with no flag \Draft */ + MAILIMAP_SEARCH_KEY_HEADER, /* messages whose given field + contains the given string */ + MAILIMAP_SEARCH_KEY_LARGER, /* messages whose size is larger then + the given size */ + MAILIMAP_SEARCH_KEY_NOT, /* not operation of the condition */ + MAILIMAP_SEARCH_KEY_OR, /* or operation between two conditions */ + MAILIMAP_SEARCH_KEY_SENTBEFORE, /* messages whose date given in Date header + is earlier than the specified date */ + MAILIMAP_SEARCH_KEY_SENTON, /* messages whose date given in Date header + is the specified date */ + MAILIMAP_SEARCH_KEY_SENTSINCE, /* messages whose date given in Date header + is later than specified date */ + MAILIMAP_SEARCH_KEY_SMALLER, /* messages whose size is smaller than + the given size */ + MAILIMAP_SEARCH_KEY_UID, /* messages whose unique identifiers are + in the given range */ + MAILIMAP_SEARCH_KEY_UNDRAFT, /* messages with no flag \Draft */ + MAILIMAP_SEARCH_KEY_SET, /* messages whose number (or unique + identifiers in case of UID SEARCH) are + in the given range */ + MAILIMAP_SEARCH_KEY_MULTIPLE /* the boolean operator between the + conditions is AND */ +}; + +/* + mailimap_search_key is the condition on the messages to return + + - type is the type of the condition + + - bcc is the text to search in the Bcc field when type is + MAILIMAP_SEARCH_KEY_BCC, should be allocated with malloc() + + - before is a date when type is MAILIMAP_SEARCH_KEY_BEFORE + + - body is the text to search in the message when type is + MAILIMAP_SEARCH_KEY_BODY, should be allocated with malloc() + + - cc is the text to search in the Cc field when type is + MAILIMAP_SEARCH_KEY_CC, should be allocated with malloc() + + - from is the text to search in the From field when type is + MAILIMAP_SEARCH_KEY_FROM, should be allocated with malloc() + + - keyword is the keyword flag name when type is MAILIMAP_SEARCH_KEY_KEYWORD, + should be allocated with malloc() + + - on is a date when type is MAILIMAP_SEARCH_KEY_ON + + - since is a date when type is MAILIMAP_SEARCH_KEY_SINCE + + - subject is the text to search in the Subject field when type is + MAILIMAP_SEARCH_KEY_SUBJECT, should be allocated with malloc() + + - text is the text to search in the text part of the message when + type is MAILIMAP_SEARCH_KEY_TEXT, should be allocated with malloc() + + - to is the text to search in the To field when type is + MAILIMAP_SEARCH_KEY_TO, should be allocated with malloc() + + - unkeyword is the keyword flag name when type is + MAILIMAP_SEARCH_KEY_UNKEYWORD, should be allocated with malloc() + + - header_name is the header name when type is MAILIMAP_SEARCH_KEY_HEADER, + should be allocated with malloc() + + - header_value is the text to search in the given header when type is + MAILIMAP_SEARCH_KEY_HEADER, should be allocated with malloc() + + - larger is a size when type is MAILIMAP_SEARCH_KEY_LARGER + + - not is a condition when type is MAILIMAP_SEARCH_KEY_NOT + + - or1 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - or2 is a condition when type is MAILIMAP_SEARCH_KEY_OR + + - sentbefore is a date when type is MAILIMAP_SEARCH_KEY_SENTBEFORE + + - senton is a date when type is MAILIMAP_SEARCH_KEY_SENTON + + - sentsince is a date when type is MAILIMAP_SEARCH_KEY_SENTSINCE + + - smaller is a size when type is MAILIMAP_SEARCH_KEY_SMALLER + + - uid is a set of messages when type is MAILIMAP_SEARCH_KEY_UID + + - set is a set of messages when type is MAILIMAP_SEARCH_KEY_SET + + - multiple is a set of message when type is MAILIMAP_SEARCH_KEY_MULTIPLE +*/ + +struct mailimap_search_key { + int sk_type; + union { + char * sk_bcc; + struct mailimap_date * sk_before; + char * sk_body; + char * sk_cc; + char * sk_from; + char * sk_keyword; + struct mailimap_date * sk_on; + struct mailimap_date * sk_since; + char * sk_subject; + char * sk_text; + char * sk_to; + char * sk_unkeyword; + struct { + char * sk_header_name; + char * sk_header_value; + } sk_header; + uint32_t sk_larger; + struct mailimap_search_key * sk_not; + struct { + struct mailimap_search_key * sk_or1; + struct mailimap_search_key * sk_or2; + } sk_or; + struct mailimap_date * sk_sentbefore; + struct mailimap_date * sk_senton; + struct mailimap_date * sk_sentsince; + uint32_t sk_smaller; + struct mailimap_set * sk_uid; + struct mailimap_set * sk_set; + clist * sk_multiple; /* list of (struct mailimap_search_key *) */ + } sk_data; +}; + +struct mailimap_search_key * +mailimap_search_key_new(int sk_type, + char * sk_bcc, struct mailimap_date * sk_before, char * sk_body, + char * sk_cc, char * sk_from, char * sk_keyword, + struct mailimap_date * sk_on, struct mailimap_date * sk_since, + char * sk_subject, char * sk_text, char * sk_to, + char * sk_unkeyword, char * sk_header_name, + char * sk_header_value, uint32_t sk_larger, + struct mailimap_search_key * sk_not, + struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2, + struct mailimap_date * sk_sentbefore, + struct mailimap_date * sk_senton, + struct mailimap_date * sk_sentsince, + uint32_t sk_smaller, struct mailimap_set * sk_uid, + struct mailimap_set * sk_set, clist * sk_multiple); + + +void mailimap_search_key_free(struct mailimap_search_key * key); + + +/* + mailimap_status_att_list is a list of mailbox STATUS request type + + - list is a list of mailbox STATUS request type + (value of elements in the list can be MAILIMAP_STATUS_ATT_MESSAGES, + MAILIMAP_STATUS_ATT_RECENT, MAILIMAP_STATUS_ATT_UIDNEXT, + MAILIMAP_STATUS_ATT_UIDVALIDITY or MAILIMAP_STATUS_ATT_UNSEEN), + each element should be allocated with malloc() +*/ + +struct mailimap_status_att_list { + clist * att_list; /* list of (uint32_t *) */ +}; + +struct mailimap_status_att_list * +mailimap_status_att_list_new(clist * att_list); + +void mailimap_status_att_list_free(struct mailimap_status_att_list * + status_att_list); + + + + +/* internal use functions */ + + +uint32_t * mailimap_number_alloc_new(uint32_t number); + +void mailimap_number_alloc_free(uint32_t * pnumber); + + +void mailimap_addr_host_free(char * addr_host); + +void mailimap_addr_mailbox_free(char * addr_mailbox); + +void mailimap_addr_adl_free(char * addr_adl); + +void mailimap_addr_name_free(char * addr_name); + +void mailimap_astring_free(char * astring); + +void mailimap_atom_free(char * atom); + +void mailimap_auth_type_free(char * auth_type); + +void mailimap_base64_free(char * base64); + +void mailimap_body_fld_desc_free(char * body_fld_desc); + +void mailimap_body_fld_id_free(char * body_fld_id); + +void mailimap_body_fld_md5_free(char * body_fld_md5); + +void mailimap_env_date_free(char * date); + +void mailimap_env_in_reply_to_free(char * in_reply_to); + +void mailimap_env_message_id_free(char * message_id); + +void mailimap_env_subject_free(char * subject); + +void mailimap_flag_extension_free(char * flag_extension); + +void mailimap_flag_keyword_free(char * flag_keyword); + +void +mailimap_header_fld_name_free(char * header_fld_name); + +void mailimap_literal_free(char * literal); + +void mailimap_mailbox_free(char * mailbox); + +void +mailimap_mailbox_data_search_free(clist * data_search); + +void mailimap_media_subtype_free(char * media_subtype); + +void mailimap_media_text_free(char * media_text); + +void mailimap_msg_att_envelope_free(struct mailimap_envelope * env); + +void +mailimap_msg_att_internaldate_free(struct mailimap_date_time * date_time); + +void +mailimap_msg_att_rfc822_free(char * str); + +void +mailimap_msg_att_rfc822_header_free(char * str); + +void +mailimap_msg_att_rfc822_text_free(char * str); + +void +mailimap_msg_att_body_free(struct mailimap_body * body); + +void +mailimap_msg_att_bodystructure_free(struct mailimap_body * body); + +void mailimap_nstring_free(char * str); + +void +mailimap_string_free(char * str); + +void mailimap_tag_free(char * tag); + +void mailimap_text_free(char * text); + + + + + +/* IMAP connection */ + +/* this is the state of the IMAP connection */ + +enum { + MAILIMAP_STATE_DISCONNECTED, + MAILIMAP_STATE_NON_AUTHENTICATED, + MAILIMAP_STATE_AUTHENTICATED, + MAILIMAP_STATE_SELECTED, + MAILIMAP_STATE_LOGOUT +}; + +/* + mailimap is an IMAP connection + + - response is a human readable message returned with a reponse, + must be accessed read-only + + - stream is the connection with the IMAP server + + - stream_buffer is the buffer where the data to parse are stored + + - state is the state of IMAP connection + + - tag is the current tag being used in IMAP connection + + - response_buffer is the buffer for response messages + + - connection_info is the information returned in response + for the last command about the connection + + - selection_info is the information returned in response + for the last command about the current selected mailbox + + - response_info is the other information returned in response + for the last command +*/ + +struct mailimap { + char * imap_response; + + /* internals */ + mailstream * imap_stream; + + size_t imap_progr_rate; + progress_function * imap_progr_fun; + + MMAPString * imap_stream_buffer; + MMAPString * imap_response_buffer; + + int imap_state; + int imap_tag; + + struct mailimap_connection_info * imap_connection_info; + struct mailimap_selection_info * imap_selection_info; + struct mailimap_response_info * imap_response_info; + + struct { + void * sasl_conn; + const char * sasl_server_fqdn; + const char * sasl_login; + const char * sasl_auth_name; + const char * sasl_password; + const char * sasl_realm; + void * sasl_secret; + } imap_sasl; +}; + +typedef struct mailimap mailimap; + + +/* + mailimap_connection_info is the information about the connection + + - capability is the list of capability of the IMAP server +*/ + +struct mailimap_connection_info { + struct mailimap_capability_data * imap_capability; +}; + +struct mailimap_connection_info * +mailimap_connection_info_new(void); + +void +mailimap_connection_info_free(struct mailimap_connection_info * conn_info); + + +/* this is the type of mailbox access */ + +enum { + MAILIMAP_MAILBOX_READONLY, + MAILIMAP_MAILBOX_READWRITE +}; + +/* + mailimap_selection_info is information about the current selected mailbox + + - perm_flags is a list of flags that can be changed permanently on the + messages of the mailbox + + - perm is the access on the mailbox, value can be + MAILIMAP_MAILBOX_READONLY or MAILIMAP_MAILBOX_READWRITE + + - uidnext is the next unique identifier + + - uidvalidity is the unique identifiers validity + + - first_unseen is the number of the first unseen message + + - flags is a list of flags that can be used on the messages of + the mailbox + + - exists is the number of messages in the mailbox + + - recent is the number of recent messages in the mailbox + + - unseen is the number of unseen messages in the mailbox +*/ + +struct mailimap_selection_info { + clist * sel_perm_flags; /* list of (struct flag_perm *) */ + int sel_perm; + uint32_t sel_uidnext; + uint32_t sel_uidvalidity; + uint32_t sel_first_unseen; + struct mailimap_flag_list * sel_flags; + uint32_t sel_exists; + uint32_t sel_recent; + uint32_t sel_unseen; +}; + +struct mailimap_selection_info * +mailimap_selection_info_new(void); + +void +mailimap_selection_info_free(struct mailimap_selection_info * sel_info); + + +/* + mailimap_response_info is the other information returned in the + response for a command + + - alert is the human readable text returned with ALERT response + + - parse is the human readable text returned with PARSE response + + - badcharset is a list of charset returned with a BADCHARSET response + + - trycreate is set to 1 if a trycreate response was returned + + - mailbox_list is a list of mailboxes + + - mailbox_lsub is a list of subscribed mailboxes + + - search_result is a list of message numbers or unique identifiers + + - status is a STATUS response + + - expunged is a list of message numbers + + - fetch_list is a list of fetch response +*/ + +struct mailimap_response_info { + char * rsp_alert; + char * rsp_parse; + clist * rsp_badcharset; /* list of (char *) */ + int rsp_trycreate; + clist * rsp_mailbox_list; /* list of (struct mailimap_mailbox_list *) */ + clist * rsp_mailbox_lsub; /* list of (struct mailimap_mailbox_list *) */ + clist * rsp_search_result; /* list of (uint32_t *) */ + struct mailimap_mailbox_data_status * rsp_status; + clist * rsp_expunged; /* list of (uint32_t 32 *) */ + clist * rsp_fetch_list; /* list of (struct mailimap_msg_att *) */ + clist * rsp_extension_list; /* list of (struct mailimap_extension_data *) */ + char * rsp_atom; + char * rsp_value; +}; + +struct mailimap_response_info * +mailimap_response_info_new(void); + +void +mailimap_response_info_free(struct mailimap_response_info * resp_info); + + +/* these are the possible returned error codes */ + +enum { + MAILIMAP_NO_ERROR = 0, + MAILIMAP_NO_ERROR_AUTHENTICATED = 1, + MAILIMAP_NO_ERROR_NON_AUTHENTICATED = 2, + MAILIMAP_ERROR_BAD_STATE, + MAILIMAP_ERROR_STREAM, + MAILIMAP_ERROR_PARSE, + MAILIMAP_ERROR_CONNECTION_REFUSED, + MAILIMAP_ERROR_MEMORY, + MAILIMAP_ERROR_FATAL, + MAILIMAP_ERROR_PROTOCOL, + MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION, + MAILIMAP_ERROR_APPEND, + MAILIMAP_ERROR_NOOP, + MAILIMAP_ERROR_LOGOUT, + MAILIMAP_ERROR_CAPABILITY, + MAILIMAP_ERROR_CHECK, + MAILIMAP_ERROR_CLOSE, + MAILIMAP_ERROR_EXPUNGE, + MAILIMAP_ERROR_COPY, + MAILIMAP_ERROR_UID_COPY, + MAILIMAP_ERROR_CREATE, + MAILIMAP_ERROR_DELETE, + MAILIMAP_ERROR_EXAMINE, + MAILIMAP_ERROR_FETCH, + MAILIMAP_ERROR_UID_FETCH, + MAILIMAP_ERROR_LIST, + MAILIMAP_ERROR_LOGIN, + MAILIMAP_ERROR_LSUB, + MAILIMAP_ERROR_RENAME, + MAILIMAP_ERROR_SEARCH, + MAILIMAP_ERROR_UID_SEARCH, + MAILIMAP_ERROR_SELECT, + MAILIMAP_ERROR_STATUS, + MAILIMAP_ERROR_STORE, + MAILIMAP_ERROR_UID_STORE, + MAILIMAP_ERROR_SUBSCRIBE, + MAILIMAP_ERROR_UNSUBSCRIBE, + MAILIMAP_ERROR_STARTTLS, + MAILIMAP_ERROR_INVAL, + MAILIMAP_ERROR_EXTENSION +}; + + +#ifdef __cplusplus +} +#endif + +#endif + Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_types_helper.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_types_helper.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1273 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_types_helper.c,v 1.12 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimap_types.h" +#include "mail.h" + +#include <stdlib.h> + +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ +/* ************************************************************************* */ + +/* in helper */ + + + + +struct mailimap_set_item * mailimap_set_item_new_single(uint32_t index) +{ + return mailimap_set_item_new(index, index); +} + +struct mailimap_set * +mailimap_set_new_single_item(struct mailimap_set_item * item) +{ + struct mailimap_set * set; + clist * list; + int r; + + list = clist_new(); + if (list == NULL) + return NULL; + + r = clist_append(list, item); + if (r < 0) { + clist_free(list); + return NULL; + } + + set = mailimap_set_new(list); + if (set == NULL) { + clist_free(list); + return NULL; + } + + return set; +} + +struct mailimap_set * mailimap_set_new_interval(uint32_t first, uint32_t last) +{ + struct mailimap_set_item * item; + struct mailimap_set * set; + + item = mailimap_set_item_new(first, last); + if (item == NULL) + return NULL; + + set = mailimap_set_new_single_item(item); + if (set == NULL) { + mailimap_set_item_free(item); + return NULL; + } + + return set; +} + +struct mailimap_set * mailimap_set_new_single(uint32_t index) +{ + return mailimap_set_new_interval(index, index); +} + + +struct mailimap_set * mailimap_set_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_set_new(list); +} + +int mailimap_set_add(struct mailimap_set * set, + struct mailimap_set_item * set_item) +{ + int r; + + r = clist_append(set->set_list, set_item); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + +int mailimap_set_add_interval(struct mailimap_set * set, + uint32_t first, uint32_t last) +{ + struct mailimap_set_item * item; + int r; + + item = mailimap_set_item_new(first, last); + if (item == NULL) + return MAILIMAP_ERROR_MEMORY; + + r = mailimap_set_add(set, item); + if (r != MAILIMAP_NO_ERROR) { + mailimap_set_item_free(item); + return r; + } + else + return MAILIMAP_NO_ERROR; +} + +int mailimap_set_add_single(struct mailimap_set * set, + uint32_t index) +{ + return mailimap_set_add_interval(set, index, index); +} + +/* CHECK */ +/* no args */ + +/* CLOSE */ +/* no args */ + +/* EXPUNGE */ +/* no args */ + +/* COPY */ +/* set and gchar */ + +/* FETCH */ +/* set and gchar fetch_type */ + + + +/* section */ + +#if 0 +/* not correct XXX */ + +struct mailimap_section * mailimap_section_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_section_new(list); +} +#endif + +static struct mailimap_section * +mailimap_section_new_msgtext(struct mailimap_section_msgtext * msgtext) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_MSGTEXT, + msgtext, NULL, NULL); + if (spec == NULL) + return NULL; + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_msgtext so that it will not be freed */ + spec->sec_data.sec_msgtext = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +static struct mailimap_section * +mailimap_section_new_part_msgtext(struct mailimap_section_part * part, + struct mailimap_section_msgtext * msgtext) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + struct mailimap_section_text * text; + + text = mailimap_section_text_new(MAILIMAP_SECTION_TEXT_SECTION_MSGTEXT, + msgtext); + if (text == NULL) + return NULL; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, + NULL, part, text); + if (spec == NULL) { + /* detach section_msgtext so that it will not be freed */ + text->sec_msgtext = NULL; + mailimap_section_text_free(text); + return NULL; + } + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_msgtext so that it will not be freed */ + text->sec_msgtext = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +/* +HEADER +HEADER.FIELDS fields +HEADER.FIELDS.NOT fields +TEXT +*/ + +struct mailimap_section * mailimap_section_new_header(void) +{ + struct mailimap_section_msgtext * msgtext; + struct mailimap_section * section; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER, + NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_header_fields(struct mailimap_header_list * header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_header_fields_not(struct mailimap_header_list * header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * mailimap_section_new_text(void) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_TEXT, NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_msgtext(msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +/* +section-part +section-part . MIME +section-part . HEADER +section-part . HEADER.FIELDS fields +section-part . HEADER.FIELDS.NOT fields +section-part . TEXT +*/ + +struct mailimap_section * +mailimap_section_new_part(struct mailimap_section_part * part) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, + NULL, part, NULL); + if (spec == NULL) + return NULL; + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_part so that it will not be freed */ + spec->sec_data.sec_part = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_part_mime(struct mailimap_section_part * part) +{ + struct mailimap_section_spec * spec; + struct mailimap_section * section; + struct mailimap_section_text * text; + + text = mailimap_section_text_new(MAILIMAP_SECTION_TEXT_MIME, NULL); + if (text == NULL) + return NULL; + + spec = mailimap_section_spec_new(MAILIMAP_SECTION_SPEC_SECTION_PART, + NULL, part, text); + if (spec == NULL) { + mailimap_section_text_free(text); + return NULL; + } + + section = mailimap_section_new(spec); + if (section == NULL) { + /* detach section_part so that it will not be freed */ + spec->sec_data.sec_part = NULL; + mailimap_section_spec_free(spec); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_part_header(struct mailimap_section_part * part) +{ + struct mailimap_section_msgtext * msgtext; + struct mailimap_section * section; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER, + NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_part_header_fields(struct mailimap_section_part * + part, + struct mailimap_header_list * + header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_part_header_fields_not(struct mailimap_section_part + * part, + struct mailimap_header_list + * header_list) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = + mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_HEADER_FIELDS_NOT, + header_list); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + /* detach header_list so that it will not be freed */ + msgtext->sec_header_list = NULL; + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +struct mailimap_section * +mailimap_section_new_part_text(struct mailimap_section_part * part) +{ + struct mailimap_section * section; + struct mailimap_section_msgtext * msgtext; + + msgtext = mailimap_section_msgtext_new(MAILIMAP_SECTION_MSGTEXT_TEXT, NULL); + if (msgtext == NULL) + return NULL; + + section = mailimap_section_new_part_msgtext(part, msgtext); + if (section == NULL) { + mailimap_section_msgtext_free(msgtext); + return NULL; + } + + return section; +} + +/* end of section */ + + + + + + +struct mailimap_fetch_att * +mailimap_fetch_att_new_envelope(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_ENVELOPE, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_flags(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_FLAGS, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_internaldate(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_INTERNALDATE, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_header(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822_HEADER, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_size(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822_SIZE, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_text(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_RFC822_TEXT, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_bodystructure(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODYSTRUCTURE, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_uid(void) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_UID, NULL, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section(struct mailimap_section * section) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_SECTION, section, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section(struct mailimap_section * section) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, section, 0, 0); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_SECTION, section, + offset, size); +} + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size) +{ + return mailimap_fetch_att_new(MAILIMAP_FETCH_ATT_BODY_PEEK_SECTION, section, + offset, size); +} + + + +struct mailimap_fetch_type * +mailimap_fetch_type_new_all(void) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_ALL, NULL, NULL); +} + +struct mailimap_fetch_type * +mailimap_fetch_type_new_full(void) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FULL, NULL, NULL); +} + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fast(void) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FAST, NULL, NULL); +} + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att(struct mailimap_fetch_att * fetch_att) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FETCH_ATT, fetch_att, NULL); +} + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list(clist * fetch_att_list) +{ + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST, + NULL, fetch_att_list); +} + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_fetch_type_new(MAILIMAP_FETCH_TYPE_FETCH_ATT_LIST, + NULL, list); +} + +int +mailimap_fetch_type_new_fetch_att_list_add(struct mailimap_fetch_type * + fetch_type, + struct mailimap_fetch_att * fetch_att) +{ + int r; + + r = clist_append(fetch_type->ft_data.ft_fetch_att_list, fetch_att); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + + + +/* STORE */ +/* set and store_att_flags */ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags(struct mailimap_flag_list * flags) +{ + return mailimap_store_att_flags_new(0, FALSE, flags); +} + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags_silent(struct mailimap_flag_list * + flags) +{ + return mailimap_store_att_flags_new(0, TRUE, flags); +} + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags(struct mailimap_flag_list * flags) +{ + return mailimap_store_att_flags_new(1, FALSE, flags); +} + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags_silent(struct mailimap_flag_list * + flags) +{ + return mailimap_store_att_flags_new(1, TRUE, flags); +} + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags(struct mailimap_flag_list * flags) +{ + return mailimap_store_att_flags_new(-1, FALSE, flags); +} + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags_silent(struct mailimap_flag_list * + flags) +{ + return mailimap_store_att_flags_new(-1, TRUE, flags); +} + +/* SEARCH */ +/* date search-key set */ + +/* + return mailimap_search_key_new(type, bcc, before, + body, cc, from, keyword, on, since, + subject, text, to, unkeyword, header_name, + header_value, larger, not, + or1, or2, sentbefore, senton, sentsince, + smaller, uid, set, multiple); +*/ + +struct mailimap_search_key * +mailimap_search_key_new_all(void) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ALL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_bcc(char * sk_bcc) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_BCC, sk_bcc, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_before(struct mailimap_date * sk_before) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_BEFORE, NULL, sk_before, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_body(char * sk_body) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_BODY, NULL, NULL, + sk_body, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_cc(char * sk_cc) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_CC, NULL, NULL, + NULL, sk_cc, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_from(char * sk_from) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FROM, NULL, NULL, + NULL, NULL, sk_from, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_keyword(char * sk_keyword) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FROM, NULL, NULL, + NULL, NULL, NULL, sk_keyword, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_on(struct mailimap_date * sk_on) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ON, NULL, NULL, + NULL, NULL, NULL, NULL, sk_on, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_since(struct mailimap_date * sk_since) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SINCE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, sk_since, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_subject(char * sk_subject) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SINCE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + sk_subject, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_text(char * sk_text) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_TEXT, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, sk_text, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_to(char * sk_to) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_TO, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, sk_to, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_unkeyword(char * sk_unkeyword) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNKEYWORD, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, sk_unkeyword, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_header(char * sk_header_name, char * sk_header_value) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_HEADER, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, sk_header_name, + sk_header_value, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_larger(uint32_t sk_larger) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_LARGER, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, sk_larger, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_not(struct mailimap_search_key * sk_not) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_NOT, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, sk_not, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_or(struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_OR, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + sk_or1, sk_or2, NULL, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_sentbefore(struct mailimap_date * sk_sentbefore) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_NOT, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, sk_sentbefore, NULL, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_senton(struct mailimap_date * sk_senton) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SENTON, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, sk_senton, NULL, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_sentsince(struct mailimap_date * sk_sentsince) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SENTSINCE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, sk_sentsince, + 0, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_smaller(uint32_t sk_smaller) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SMALLER, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + sk_smaller, NULL, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_uid(struct mailimap_set * sk_uid) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UID, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, sk_uid, NULL, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_set(struct mailimap_set * sk_set) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SET, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, sk_set, NULL); +} + +struct mailimap_search_key * +mailimap_search_key_new_multiple(clist * sk_multiple) +{ + return mailimap_search_key_new(MAILIMAP_SEARCH_KEY_MULTIPLE, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, 0, NULL, + NULL, NULL, NULL, NULL, NULL, + 0, NULL, NULL, sk_multiple); +} + +struct mailimap_search_key * +mailimap_search_key_new_multiple_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_search_key_new_multiple(list); +} + +int +mailimap_search_key_multiple_add(struct mailimap_search_key * keys, + struct mailimap_search_key * key_item) +{ + int r; + + r = clist_append(keys->sk_data.sk_multiple, key_item); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + + + +/* CAPABILITY */ +/* no args */ + +/* LOGOUT */ +/* no args */ + +/* NOOP */ +/* no args */ + +/* APPEND */ +/* gchar flag_list date_time gchar */ + +struct mailimap_flag_list * +mailimap_flag_list_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_flag_list_new(list); +} + +int mailimap_flag_list_add(struct mailimap_flag_list * flag_list, + struct mailimap_flag * f) +{ + int r; + + r = clist_append(flag_list->fl_list, f); + if (r < 0) + return MAILIMAP_ERROR_MEMORY; + + return MAILIMAP_NO_ERROR; +} + +struct mailimap_flag * mailimap_flag_new_answered(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_ANSWERED, NULL, NULL); +} + +struct mailimap_flag * mailimap_flag_new_flagged(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_FLAGGED, NULL, NULL); +} + +struct mailimap_flag * mailimap_flag_new_deleted(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_DELETED, NULL, NULL); +} + +struct mailimap_flag * mailimap_flag_new_seen(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_SEEN, NULL, NULL); +} + +struct mailimap_flag * mailimap_flag_new_draft(void) +{ + return mailimap_flag_new(MAILIMAP_FLAG_DRAFT, NULL, NULL); +} + +struct mailimap_flag * mailimap_flag_new_flag_keyword(char * flag_keyword) +{ + return mailimap_flag_new(MAILIMAP_FLAG_KEYWORD, flag_keyword, NULL); +} + +struct mailimap_flag * mailimap_flag_new_flag_extension(char * flag_extension) +{ + return mailimap_flag_new(MAILIMAP_FLAG_EXTENSION, NULL, flag_extension); +} + + + + +/* CREATE */ +/* gchar */ + +/* DELETE */ +/* gchar */ + +/* EXAMINE */ +/* gchar */ + +/* LIST */ +/* gchar gchar */ + +/* LSUB */ +/* gchar gchar */ + +/* RENAME */ +/* gchar gchar */ + +/* SELECT */ +/* gchar */ + +/* STATUS */ +/* gchar GList of status_att */ + +struct mailimap_status_att_list * mailimap_status_att_list_new_empty(void) +{ + clist * list; + + list = clist_new(); + if (list == NULL) + return NULL; + + return mailimap_status_att_list_new(list); +} + +int +mailimap_status_att_list_add(struct mailimap_status_att_list * sa_list, + int status_att) +{ + int * pstatus_att; + int r; + + pstatus_att = malloc(sizeof(* pstatus_att)); + * pstatus_att = status_att; + + r = clist_append(sa_list->att_list, pstatus_att); + if (r < 0) { + free(pstatus_att); + return MAILIMAP_ERROR_MEMORY; + } + + return MAILIMAP_NO_ERROR; +} + +/* SUBSCRIBE */ +/* gchar */ + +/* UNSUBSCRIBE */ +/* gchar */ + +/* LOGIN */ +/* gchar gchar */ + +/* AUTHENTICATE */ +/* gchar */ + + +static int recursive_build_path(struct mailimap_body * root_part, + struct mailimap_body * part, + clist ** result); + +static int try_build_part(struct mailimap_body * root_part, + struct mailimap_body * part, uint32_t count, + clist ** result) +{ + int r; + clist * imap_id_list; + uint32_t * id; + + r = recursive_build_path(root_part, part, &imap_id_list); + if (r != MAILIMAP_NO_ERROR) + return r; + + id = malloc(sizeof(* id)); + if (id == NULL) { + clist_free(imap_id_list); + return MAILIMAP_ERROR_MEMORY; + } + + * id = count; + + r = clist_prepend(imap_id_list, id); + if (r < 0) { + free(id); + clist_free(imap_id_list); + return MAILIMAP_ERROR_MEMORY; + } + + * result = imap_id_list; + + return MAILIMAP_NO_ERROR; +} + + +static int recursive_build_path(struct mailimap_body * root_part, + struct mailimap_body * part, + clist ** result) +{ + clistiter * cur; + uint32_t count; + int r; + clist * imap_id_list; + + if (part == root_part) { + imap_id_list = clist_new(); + if (imap_id_list == NULL) { + return MAILIMAP_ERROR_MEMORY; + } + + * result = imap_id_list; + + return MAILIMAP_NO_ERROR; + } + + switch (root_part->bd_type) { + case MAILIMAP_BODY_MPART: + count = 0; + for(cur = clist_begin(root_part->bd_data.bd_body_mpart->bd_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_body * current_part; + + current_part = clist_content(cur); + count ++; + + r = try_build_part(current_part, part, count, &imap_id_list); + if (r == MAILIMAP_ERROR_INVAL) { + continue; + } if (r != MAILIMAP_NO_ERROR) { + return r; + } + else { + * result = imap_id_list; + return MAILIMAP_NO_ERROR; + } + } + return MAILIMAP_ERROR_INVAL; + + case MAILIMAP_BODY_1PART: + if (root_part->bd_data.bd_body_1part->bd_type == + MAILIMAP_BODY_TYPE_1PART_MSG) { + struct mailimap_body * current_part; + + current_part = + root_part->bd_data.bd_body_1part->bd_data.bd_type_msg->bd_body; + + r = try_build_part(current_part, part, 1, &imap_id_list); + if (r != MAILIMAP_NO_ERROR) { + return r; + } + else { + * result = imap_id_list; + return MAILIMAP_NO_ERROR; + } + } + else { + return MAILIMAP_ERROR_INVAL; + } + break; + + default: + return MAILIMAP_ERROR_INVAL; + } +} + +/* return mailimap_section_part from a given mailimap_body */ + +int mailimap_get_section_part_from_body(struct mailimap_body * root_part, + struct mailimap_body * part, + struct mailimap_section_part ** result) +{ + struct mailimap_section_part * section_part; + clist * id_list; + int r; + int res; + + r = recursive_build_path(root_part, part, &id_list); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + section_part = mailimap_section_part_new(id_list); + if (section_part == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_list; + } + + * result = section_part; + + return MAILIMAP_NO_ERROR; + + free_list: + clist_foreach(id_list, (clist_func) free, NULL); + clist_free(id_list); + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_types_helper.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/mailimap_types_helper.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,758 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimap_types_helper.h,v 1.11 2004/11/21 21:53:37 hoa Exp $ + */ + +#ifndef MAILIMAP_TYPES_HELPER_H + +#define MAILIMAP_TYPES_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailimap_types.h> + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + this function creates a new set item with a single message + given by index +*/ + +struct mailimap_set_item * mailimap_set_item_new_single(uint32_t index); + +/* + this function creates a new set with one set item + */ + +struct mailimap_set * +mailimap_set_new_single_item(struct mailimap_set_item * item); + +/* + this function creates a set with a single interval +*/ + +struct mailimap_set * mailimap_set_new_interval(uint32_t first, uint32_t last); + +/* + this function creates a set with a single message +*/ + +struct mailimap_set * mailimap_set_new_single(uint32_t index); + +/* + this function creates an empty set of messages +*/ + +struct mailimap_set * mailimap_set_new_empty(void); + +/* + this function adds a set item to the set of messages + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_set_add(struct mailimap_set * set, + struct mailimap_set_item * set_item); + +/* + this function adds an interval to the set + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_set_add_interval(struct mailimap_set * set, + uint32_t first, uint32_t last); + +/* + this function adds a single message to the set + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_set_add_single(struct mailimap_set * set, + uint32_t index); + +/* + this function creates a mailimap_section structure to request + the header of a message +*/ + +struct mailimap_section * mailimap_section_new_header(void); + +/* + this functions creates a mailimap_section structure to describe + a list of headers +*/ + +struct mailimap_section * +mailimap_section_new_header_fields(struct mailimap_header_list * header_list); + +/* + this functions creates a mailimap_section structure to describe headers + other than those given +*/ + +struct mailimap_section * +mailimap_section_new_header_fields_not(struct mailimap_header_list * header_list); + +/* + this function creates a mailimap_section structure to describe the + text of a message + */ + +struct mailimap_section * mailimap_section_new_text(void); + +/* + this function creates a mailimap_section structure to describe the + content of a MIME part +*/ + +struct mailimap_section * +mailimap_section_new_part(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe the + MIME fields of a MIME part +*/ + +struct mailimap_section * +mailimap_section_new_part_mime(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe the + headers of a MIME part if the MIME type is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_header(struct mailimap_section_part * part); + +/* + this function creates a mailimap_section structure to describe + a list of headers of a MIME part if the MIME type is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_header_fields(struct mailimap_section_part * + part, + struct mailimap_header_list * + header_list); + +/* + this function creates a mailimap_section structure to describe + headers of a MIME part other than those given if the MIME type + is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_header_fields_not(struct mailimap_section_part + * part, + struct mailimap_header_list + * header_list); + +/* + this function creates a mailimap_section structure to describe + text part of message if the MIME type is a message/rfc822 +*/ + +struct mailimap_section * +mailimap_section_new_part_text(struct mailimap_section_part * part); + + +/* + this function creates a mailimap_fetch_att structure to request + envelope of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_envelope(void); + + +/* + this function creates a mailimap_fetch_att structure to request + flags of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_flags(void); + +/* + this function creates a mailimap_fetch_att structure to request + internal date of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_internaldate(void); + + +/* + this function creates a mailimap_fetch_att structure to request + text part of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822(void); + + +/* + this function creates a mailimap_fetch_att structure to request + header of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_header(void); + +/* + this function creates a mailimap_fetch_att structure to request + size of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_size(void); + +/* + this function creates a mailimap_fetch_att structure to request + envelope of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_rfc822_text(void); + +/* + this function creates a mailimap_fetch_att structure to request + the MIME structure of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body(void); + +/* + this function creates a mailimap_fetch_att structure to request + the MIME structure of a message and additional MIME information +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_bodystructure(void); + +/* + this function creates a mailimap_fetch_att structure to request + unique identifier of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_uid(void); + +/* + this function creates a mailimap_fetch_att structure to request + a given section of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section(struct mailimap_section * section); + +/* + this function creates a mailimap_fetch_att structure to request + a given section of a message without marking it as read +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section(struct mailimap_section * section); + +/* + this function creates a mailimap_fetch_att structure to request + a part of a section of a message +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size); + +/* + this function creates a mailimap_fetch_att structure to request + a part of a section of a message without marking it as read +*/ + +struct mailimap_fetch_att * +mailimap_fetch_att_new_body_peek_section_partial(struct mailimap_section * section, + uint32_t offset, uint32_t size); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE) of a message +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_all(void); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY) +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_full(void); + +/* + this function creates a mailimap_fetch_type structure to request + (FLAGS INTERNALDATE RFC822.SIZE) +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fast(void); + +/* + this function creates a mailimap_fetch_type structure to request + the given fetch attribute +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att(struct mailimap_fetch_att * fetch_att); + +/* + this function creates a mailimap_fetch_type structure to request + the list of fetch attributes +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list(clist * fetch_att_list); + +/* + this function creates a mailimap_fetch_type structure +*/ + +struct mailimap_fetch_type * +mailimap_fetch_type_new_fetch_att_list_empty(void); + +/* + this function adds a given fetch attribute to the mailimap_fetch + structure + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int +mailimap_fetch_type_new_fetch_att_list_add(struct mailimap_fetch_type * + fetch_type, + struct mailimap_fetch_att * + fetch_att); + +/* + this function creates a store attribute to set the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to silently set the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_set_flags_silent(struct mailimap_flag_list * + flags); + +/* + this function creates a store attribute to add the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to add silently the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_add_flags_silent(struct mailimap_flag_list * + flags); + +/* + this function creates a store attribute to remove the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags(struct mailimap_flag_list * flags); + +/* + this function creates a store attribute to remove silently the given flags +*/ + +struct mailimap_store_att_flags * +mailimap_store_att_flags_new_remove_flags_silent(struct mailimap_flag_list * + flags); + + +/* + this function creates a condition structure to match all messages +*/ + +struct mailimap_search_key * +mailimap_search_key_new_all(void); + +/* + this function creates a condition structure to match messages with Bcc field + + @param bcc this is the content of Bcc to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_bcc(char * sk_bcc); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +struct mailimap_search_key * +mailimap_search_key_new_before(struct mailimap_date * sk_before); + +/* + this function creates a condition structure to match messages with + message content + + @param body this is the content of the message to match, it should + be allocated with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_body(char * sk_body); + +/* + this function creates a condition structure to match messages with + Cc field + + + @param cc this is the content of Cc to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_cc(char * sk_cc); + +/* + this function creates a condition structure to match messages with + From field + + @param from this is the content of From to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_from(char * sk_from); + +/* + this function creates a condition structure to match messages with + a flag given by keyword +*/ + +struct mailimap_search_key * +mailimap_search_key_new_keyword(char * sk_keyword); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +struct mailimap_search_key * +mailimap_search_key_new_on(struct mailimap_date * sk_on); + +/* + this function creates a condition structure to match messages with + internal date +*/ + +struct mailimap_search_key * +mailimap_search_key_new_since(struct mailimap_date * sk_since); + +/* + this function creates a condition structure to match messages with + Subject field + + @param subject this is the content of Subject to match, it should + be allocated with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_subject(char * sk_subject); + +/* + this function creates a condition structure to match messages with + message text part + + @param text this is the message text to match, it should + be allocated with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_text(char * sk_text); + +/* + this function creates a condition structure to match messages with + To field + + @param to this is the content of To to match, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_to(char * sk_to); + +/* + this function creates a condition structure to match messages with + no a flag given by unkeyword +*/ + +struct mailimap_search_key * +mailimap_search_key_new_unkeyword(char * sk_unkeyword); + +/* + this function creates a condition structure to match messages with + the given field + + @param header_name this is the name of the field to match, it + should be allocated with malloc() + + @param header_value this is the content, it should be allocated + with malloc() +*/ + +struct mailimap_search_key * +mailimap_search_key_new_header(char * sk_header_name, char * sk_header_value); + + +/* + this function creates a condition structure to match messages with size +*/ + +struct mailimap_search_key * +mailimap_search_key_new_larger(uint32_t sk_larger); + +/* + this function creates a condition structure to match messages that + do not match the given condition +*/ + +struct mailimap_search_key * +mailimap_search_key_new_not(struct mailimap_search_key * sk_not); + +/* + this function creates a condition structure to match messages that + match one of the given conditions +*/ + +struct mailimap_search_key * +mailimap_search_key_new_or(struct mailimap_search_key * sk_or1, + struct mailimap_search_key * sk_or2); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +struct mailimap_search_key * +mailimap_search_key_new_sentbefore(struct mailimap_date * sk_sentbefore); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +struct mailimap_search_key * +mailimap_search_key_new_senton(struct mailimap_date * sk_senton); + +/* + this function creates a condition structure to match messages + with Date field +*/ + +struct mailimap_search_key * +mailimap_search_key_new_sentsince(struct mailimap_date * sk_sentsince); + +/* + this function creates a condition structure to match messages with size +*/ + +struct mailimap_search_key * +mailimap_search_key_new_smaller(uint32_t sk_smaller); + +/* + this function creates a condition structure to match messages with unique + identifier +*/ + +struct mailimap_search_key * +mailimap_search_key_new_uid(struct mailimap_set * sk_uid); + +/* + this function creates a condition structure to match messages with number + or unique identifier (depending whether SEARCH or UID SEARCH is used) +*/ + +struct mailimap_search_key * +mailimap_search_key_new_set(struct mailimap_set * sk_set); + +/* + this function creates a condition structure to match messages that match + all the conditions given in the list +*/ + +struct mailimap_search_key * +mailimap_search_key_new_multiple(clist * sk_multiple); + + +/* + same as previous but the list is empty +*/ + +struct mailimap_search_key * +mailimap_search_key_new_multiple_empty(void); + +/* + this function adds a condition to the condition list + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int +mailimap_search_key_multiple_add(struct mailimap_search_key * keys, + struct mailimap_search_key * key_item); + + +/* + this function creates an empty list of flags +*/ + +struct mailimap_flag_list * +mailimap_flag_list_new_empty(void); + +/* + this function adds a flag to the list of flags + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimap_flag_list_add(struct mailimap_flag_list * flag_list, + struct mailimap_flag * f); + +/* + this function creates a \Answered flag +*/ + +struct mailimap_flag * mailimap_flag_new_answered(void); + +/* + this function creates a \Flagged flag +*/ + +struct mailimap_flag * mailimap_flag_new_flagged(void); + +/* + this function creates a \Deleted flag +*/ + +struct mailimap_flag * mailimap_flag_new_deleted(void); + +/* + this function creates a \Seen flag +*/ + +struct mailimap_flag * mailimap_flag_new_seen(void); + +/* + this function creates a \Draft flag +*/ + +struct mailimap_flag * mailimap_flag_new_draft(void); + +/* + this function creates a keyword flag + + @param flag_keyword this should be allocated with malloc() +*/ + +struct mailimap_flag * mailimap_flag_new_flag_keyword(char * flag_keyword); + + +/* + this function creates an extension flag + + @param flag_extension this should be allocated with malloc() +*/ + +struct mailimap_flag * mailimap_flag_new_flag_extension(char * flag_extension); + +/* + this function creates an empty list of status attributes +*/ + +struct mailimap_status_att_list * mailimap_status_att_list_new_empty(void); + +/* + this function adds status attributes to the list + + @return MAILIMAP_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int +mailimap_status_att_list_add(struct mailimap_status_att_list * sa_list, + int status_att); + +/* return mailimap_section_part from a given mailimap_body */ + +int mailimap_get_section_part_from_body(struct mailimap_body * root_part, + struct mailimap_body * part, + struct mailimap_section_part ** result); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,282 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimap.h" +#include "mailimap_extension.h" +#include "uidplus.h" +#include "uidplus_types.h" +#include "uidplus_parser.h" +#include "mailimap_sender.h" +#include "uidplus_sender.h" + +#include <stdio.h> +#include <stdlib.h> + +void +mailimap_uidplus_free(struct mailimap_extension_data * ext_data); + +LIBETPAN_EXPORT +struct mailimap_extension_api mailimap_extension_uidplus = { +#if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L + /* name */ "UIDPLUS", + /* extension_id */ MAILIMAP_EXTENSION_UIDPLUS, + /* parser */ mailimap_uidplus_parse, + /* free */ mailimap_uidplus_free, +#else + .name = "UIDPLUS", + .extension_id = MAILIMAP_EXTENSION_UIDPLUS, + .parser = mailimap_uidplus_parse, + .free = mailimap_uidplus_free, +#endif +}; + +LIBETPAN_EXPORT +int mailimap_uid_expunge(mailimap * session, struct mailimap_set * set) +{ + struct mailimap_response * response; + int r; + int error_code; + + if (session->imap_state != MAILIMAP_STATE_SELECTED) + return MAILIMAP_ERROR_BAD_STATE; + + r = send_current_tag(session); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uid_expunge_send(session->imap_stream, set); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_crlf_send(session->imap_stream); + if (r != MAILIMAP_NO_ERROR) + return r; + + if (mailstream_flush(session->imap_stream) == -1) + return MAILIMAP_ERROR_STREAM; + + if (read_line(session) == NULL) + return MAILIMAP_ERROR_STREAM; + + r = parse_response(session, &response); + if (r != MAILIMAP_NO_ERROR) + return r; + + error_code = response->rsp_resp_done->rsp_data.rsp_tagged->rsp_cond_state->rsp_type; + + mailimap_response_free(response); + + switch (error_code) { + case MAILIMAP_RESP_COND_STATE_OK: + return MAILIMAP_NO_ERROR; + + default: + return MAILIMAP_ERROR_EXPUNGE; + } +} + +static void extract_copy_uid(mailimap * session, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result) +{ + clistiter * cur; + + * uidvalidity_result = 0; + * source_result = NULL; + * dest_result = NULL; + + if (session->imap_response_info == NULL) { + return; + } + + for(cur = clist_begin(session->imap_response_info->rsp_extension_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + struct mailimap_uidplus_resp_code_copy * resp_code_copy; + + ext_data = clist_content(cur); + if (ext_data->ext_extension != &mailimap_extension_uidplus) + continue; + + if (ext_data->ext_type != MAILIMAP_UIDPLUS_RESP_CODE_COPY) + continue; + + resp_code_copy = ext_data->ext_data; + + * uidvalidity_result = resp_code_copy->uid_uidvalidity; + * source_result = resp_code_copy->uid_source_set; + * dest_result = resp_code_copy->uid_dest_set; + resp_code_copy->uid_source_set = NULL; + resp_code_copy->uid_dest_set = NULL; + break; + } +} + +LIBETPAN_EXPORT +int mailimap_uidplus_copy(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result) +{ + int r; + + r = mailimap_copy(session, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + extract_copy_uid(session, uidvalidity_result, source_result, dest_result); + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_uidplus_uid_copy(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result) +{ + int r; + + r = mailimap_uid_copy(session, set, mb); + if (r != MAILIMAP_NO_ERROR) + return r; + + extract_copy_uid(session, uidvalidity_result, source_result, dest_result); + + return MAILIMAP_NO_ERROR; +} + +static void extract_apnd_uid(mailimap * session, + uint32_t * uidvalidity_result, + struct mailimap_set ** result) +{ + clistiter * cur; + + * uidvalidity_result = 0; + * result = NULL; + + if (session->imap_response_info == NULL) { + return; + } + + for(cur = clist_begin(session->imap_response_info->rsp_extension_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailimap_extension_data * ext_data; + struct mailimap_uidplus_resp_code_apnd * resp_code_apnd; + + ext_data = clist_content(cur); + if (ext_data->ext_extension != &mailimap_extension_uidplus) + continue; + + if (ext_data->ext_type != MAILIMAP_UIDPLUS_RESP_CODE_APND) + continue; + + resp_code_apnd = ext_data->ext_data; + + * uidvalidity_result = resp_code_apnd->uid_uidvalidity; + * result = resp_code_apnd->uid_set; + resp_code_apnd->uid_set = NULL; + break; + } +} + +static void extract_apnd_single_uid(mailimap * session, + uint32_t * uidvalidity_result, + uint32_t * uid_result) +{ + struct mailimap_set * set; + + extract_apnd_uid(session, uidvalidity_result, &set); + * uid_result = 0; + if (set != NULL) { + clistiter * cur; + + cur = clist_begin(set->set_list); + if (cur != NULL) { + struct mailimap_set_item * item; + + item = clist_content(cur); + * uid_result = item->set_first; + } + mailimap_set_free(set); + } +} + +LIBETPAN_EXPORT +int mailimap_uidplus_append(mailimap * session, const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + const char * literal, size_t literal_size, + uint32_t * uidvalidity_result, + uint32_t * uid_result) +{ + int r; + + r = mailimap_append(session, mailbox, flag_list, date_time, + literal, literal_size); + if (r != MAILIMAP_NO_ERROR) + return r; + + extract_apnd_single_uid(session, uidvalidity_result, uid_result); + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_uidplus_append_simple(mailimap * session, const char * mailbox, + const char * content, uint32_t size, + uint32_t * uidvalidity_result, + uint32_t * uid_result) +{ + int r; + + r = mailimap_append_simple(session, mailbox, + content, size); + if (r != MAILIMAP_NO_ERROR) + return r; + + extract_apnd_single_uid(session, uidvalidity_result, uid_result); + + return MAILIMAP_NO_ERROR; +} + +LIBETPAN_EXPORT +int mailimap_has_uidplus(mailimap * session) +{ + return mailimap_has_extension(session, "UIDPLUS"); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,54 @@ +#ifndef UIDPLUS_H + +#define UIDPLUS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/libetpan-config.h> +#include <libetpan/mailimap_types.h> +#include <libetpan/uidplus_types.h> + +LIBETPAN_EXPORT +extern struct mailimap_extension_api mailimap_extension_uidplus; + +LIBETPAN_EXPORT +int mailimap_uid_expunge(mailimap * session, struct mailimap_set * set); + +LIBETPAN_EXPORT +int mailimap_uidplus_copy(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result); + +LIBETPAN_EXPORT +int mailimap_uidplus_uid_copy(mailimap * session, struct mailimap_set * set, + const char * mb, + uint32_t * uidvalidity_result, + struct mailimap_set ** source_result, + struct mailimap_set ** dest_result); + +LIBETPAN_EXPORT +int mailimap_uidplus_append(mailimap * session, const char * mailbox, + struct mailimap_flag_list * flag_list, + struct mailimap_date_time * date_time, + const char * literal, size_t literal_size, + uint32_t * uidvalidity_result, + uint32_t * uid_result); + +LIBETPAN_EXPORT +int mailimap_uidplus_append_simple(mailimap * session, const char * mailbox, + const char * content, uint32_t size, + uint32_t * uidvalidity_result, + uint32_t * uid_result); + +LIBETPAN_EXPORT +int mailimap_has_uidplus(mailimap * session); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_parser.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_parser.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,379 @@ +#include "uidplus_parser.h" + +#include <stdio.h> +#include <stdlib.h> + +#include "mailimap_parser.h" +#include "mailimap_keywords.h" +#include "mailimap_extension.h" +#include "uidplus_types.h" +#include "uidplus.h" + +static int mailimap_uid_range_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_set_item ** result); + +static int mailimap_uidplus_resp_code_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_extension_data ** result); + +int mailimap_uidplus_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, size_t * index, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + if (calling_parser != MAILIMAP_EXTENDED_PARSER_RESP_TEXT_CODE) + return MAILIMAP_ERROR_PARSE; + + return mailimap_uidplus_resp_code_parse(fd, buffer, index, result); +} + + +/* + uid-set = (uniqueid / uid-range) *("," uid-set) +*/ + +static int uid_set_item_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_set_item ** result, + size_t progr_rate, + progress_function * progr_fun) +{ + int r; + struct mailimap_set_item * set_item; + uint32_t uniqueid; + size_t cur_token; + + cur_token = * index; + + r = mailimap_uid_range_parse(fd, buffer, &cur_token, &set_item); + if (r == MAILIMAP_NO_ERROR) { + * result = set_item; + * index = cur_token; + return r; + } + + if (r != MAILIMAP_ERROR_PARSE) + return r; + + r = mailimap_uniqueid_parse(fd, buffer, &cur_token, &uniqueid); + if (r == MAILIMAP_NO_ERROR) { + set_item = mailimap_set_item_new(uniqueid, uniqueid); + if (set_item == NULL) + return MAILIMAP_ERROR_MEMORY; + + * result = set_item; + * index = cur_token; + + return MAILIMAP_NO_ERROR; + } + + return r; +} + +static void uid_set_item_destructor(struct mailimap_set_item * set_item) +{ + mailimap_set_item_free(set_item); +} + +static int mailimap_uid_set_parse(mailstream * fd, MMAPString *buffer, + size_t * index, + struct mailimap_set ** result) +{ + int r; + clist * list; + struct mailimap_set * set; + size_t cur_token; + + cur_token = * index; + + r = mailimap_struct_list_parse(fd, buffer, &cur_token, &list, + ',', + (mailimap_struct_parser *) uid_set_item_parse, + (mailimap_struct_destructor *) uid_set_item_destructor, + 0, NULL); + if (r != MAILIMAP_NO_ERROR) + return r; + + set = mailimap_set_new(list); + if (set == NULL) { + clistiter * cur; + + for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) { + struct mailimap_set_item * item; + + item = clist_content(cur); + free(item); + } + clist_free(list); + return MAILIMAP_ERROR_MEMORY; + } + + * result = set; + * index = cur_token; + + return MAILIMAP_NO_ERROR; +} + +/* + uid-range = (uniqueid ":" uniqueid) + ; two uniqueid values and all values + ; between these two regards of order. + ; Example: 2:4 and 4:2 are equivalent. +*/ + +static int mailimap_uid_range_parse(mailstream * fd, MMAPString * buffer, + size_t * index, struct mailimap_set_item ** result) +{ + uint32_t first; + uint32_t last; + int r; + struct mailimap_set_item * item; + size_t cur_token; + + cur_token = * index; + + r = mailimap_uniqueid_parse(fd, buffer, &cur_token, &first); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_colon_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_uniqueid_parse(fd, buffer, &cur_token, &last); + if (r != MAILIMAP_NO_ERROR) + return r; + + item = mailimap_set_item_new(first, last); + if (item == NULL) + return MAILIMAP_ERROR_MEMORY; + + * index = cur_token; + * result = item; + + return MAILIMAP_NO_ERROR; +} + +/* + append-uid = uniqueid + + append-uid =/ uid-set + ; only permitted if client uses [MULTIAPPEND] + ; to append multiple messages. +*/ + +static int mailimap_append_uid_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_set ** result) +{ + return mailimap_uid_set_parse(fd, buffer, index, result); +} + +/* + resp-code-apnd = "APPENDUID" SP nz-number SP append-uid +*/ + +static int mailimap_resp_code_apnd_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_uidplus_resp_code_apnd ** result) +{ + int r; + size_t cur_token; + uint32_t uidvalidity; + struct mailimap_set * set; + struct mailimap_uidplus_resp_code_apnd * resp_code_apnd; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "APPENDUID"); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_nz_number_parse(fd, buffer, &cur_token, &uidvalidity); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) + return r; + + r = mailimap_append_uid_parse(fd, buffer, &cur_token, &set); + if (r != MAILIMAP_NO_ERROR) + return r; + + resp_code_apnd = mailimap_uidplus_resp_code_apnd_new(uidvalidity, set); + if (resp_code_apnd == NULL) { + mailimap_set_free(set); + return MAILIMAP_ERROR_MEMORY; + } + + * index = cur_token; + * result = resp_code_apnd; + + return MAILIMAP_NO_ERROR; +} + +/* + resp-code-copy = "COPYUID" SP nz-number SP uid-set SP uid-set +*/ + +static int mailimap_resp_code_copy_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_uidplus_resp_code_copy ** result) +{ + int r; + size_t cur_token; + uint32_t uidvalidity; + struct mailimap_set * source_set; + struct mailimap_set * dest_set; + struct mailimap_uidplus_resp_code_copy * resp_code_copy; + int res; + + cur_token = * index; + + r = mailimap_token_case_insensitive_parse(fd, buffer, &cur_token, + "COPYUID"); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_nz_number_parse(fd, buffer, &cur_token, &uidvalidity); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_uid_set_parse(fd, buffer, &cur_token, &source_set); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto err; + } + + r = mailimap_space_parse(fd, buffer, &cur_token); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_source_set; + } + + r = mailimap_uid_set_parse(fd, buffer, &cur_token, &dest_set); + if (r != MAILIMAP_NO_ERROR) { + res = r; + goto free_source_set; + } + + resp_code_copy = mailimap_uidplus_resp_code_copy_new(uidvalidity, + source_set, dest_set); + if (resp_code_copy == NULL) { + res = MAILIMAP_ERROR_MEMORY; + goto free_dest_set; + } + + * index = cur_token; + * result = resp_code_copy; + + return MAILIMAP_NO_ERROR; + + free_dest_set: + mailimap_set_free(dest_set); + free_source_set: + mailimap_set_free(source_set); + err: + return res; +} + +/* + "UIDNOTSTICKY" +*/ + +static int mailimap_uidplus_uidnotsticky_parse(mailstream * fd, MMAPString * buffer, + size_t * index) +{ + return mailimap_token_case_insensitive_parse(fd, buffer, index, + "UIDNOTSTICKY"); +} + +/* + resp-text-code =/ resp-code-apnd / resp-code-copy / "UIDNOTSTICKY" + ; incorporated before the expansion rule of + ; atom [SP 1*<any TEXT-CHAR except "]">] + ; that appears in [IMAP] +*/ + +static int mailimap_uidplus_resp_code_parse(mailstream * fd, MMAPString * buffer, + size_t * index, + struct mailimap_extension_data ** result) +{ + struct mailimap_uidplus_resp_code_apnd * resp_code_apnd; + struct mailimap_uidplus_resp_code_copy * resp_code_copy; + size_t cur_token; + struct mailimap_extension_data * ext; + int r; + + cur_token = * index; + + r = mailimap_resp_code_apnd_parse(fd, buffer, &cur_token, &resp_code_apnd); + if (r == MAILIMAP_NO_ERROR) { + ext = mailimap_extension_data_new(&mailimap_extension_uidplus, + MAILIMAP_UIDPLUS_RESP_CODE_APND, resp_code_apnd); + if (ext == NULL) { + mailimap_uidplus_resp_code_apnd_free(resp_code_apnd); + return MAILIMAP_ERROR_MEMORY; + } + + * index = cur_token; + * result = ext; + + return MAILIMAP_NO_ERROR; + } + + r = mailimap_resp_code_copy_parse(fd, buffer, &cur_token, &resp_code_copy); + if (r == MAILIMAP_NO_ERROR) { + ext = mailimap_extension_data_new(&mailimap_extension_uidplus, + MAILIMAP_UIDPLUS_RESP_CODE_COPY, resp_code_copy); + if (ext == NULL) { + mailimap_uidplus_resp_code_copy_free(resp_code_copy); + return MAILIMAP_ERROR_MEMORY; + } + + * index = cur_token; + * result = ext; + + return MAILIMAP_NO_ERROR; + } + + r = mailimap_uidplus_uidnotsticky_parse(fd, buffer, &cur_token); + if (r == MAILIMAP_NO_ERROR) { + ext = mailimap_extension_data_new(&mailimap_extension_uidplus, + MAILIMAP_UIDPLUS_RESP_CODE_UIDNOTSTICKY, resp_code_copy); + if (ext == NULL) { + mailimap_uidplus_resp_code_copy_free(resp_code_copy); + return MAILIMAP_ERROR_MEMORY; + } + + * index = cur_token; + * result = ext; + + return MAILIMAP_NO_ERROR; + } + + return MAILIMAP_ERROR_PARSE; +} + Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_parser.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_parser.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,25 @@ +#ifndef UIDPLUS_PARSER_H + +#define UIDPLUS_PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> +#include "mailstream_types.h" +#include "mmapstring.h" +#include "mailimap_types.h" +#include "mailimap_extension_types.h" + +int mailimap_uidplus_parse(int calling_parser, mailstream * fd, + MMAPString * buffer, size_t * index, + struct mailimap_extension_data ** result, + size_t progr_rate, + progress_function * progr_fun); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_sender.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_sender.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,28 @@ +#include "uidplus_sender.h" + +#include "mailimap_sender.h" + +int +mailimap_uid_expunge_send(mailstream * fd, + struct mailimap_set * set) +{ + int r; + + r = mailimap_token_send(fd, "UID"); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_expunge_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_space_send(fd); + if (r != MAILIMAP_NO_ERROR) + return r; + r = mailimap_set_send(fd, set); + if (r != MAILIMAP_NO_ERROR) + return r; + + return MAILIMAP_NO_ERROR; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_sender.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_sender.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,22 @@ +#ifndef UIDPLUS_SENDER_H + +#define UIDPLUS_SENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/libetpan-config.h> + +#include "mailimap_types.h" +#include "mailstream_types.h" + +int +mailimap_uid_expunge_send(mailstream * fd, + struct mailimap_set * set); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_types.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_types.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,69 @@ +#include "uidplus_types.h" + +#include <stdio.h> +#include <stdlib.h> +#include "mailimap_extension_types.h" + +struct mailimap_uidplus_resp_code_apnd * mailimap_uidplus_resp_code_apnd_new(uint32_t uid_uidvalidity, struct mailimap_set * uid_set) +{ + struct mailimap_uidplus_resp_code_apnd * resp_code_apnd; + + resp_code_apnd = malloc(sizeof(* resp_code_apnd)); + if (resp_code_apnd == NULL) + return NULL; + + resp_code_apnd->uid_uidvalidity = uid_uidvalidity; + resp_code_apnd->uid_set = uid_set; + + return resp_code_apnd; +} + +void mailimap_uidplus_resp_code_apnd_free(struct mailimap_uidplus_resp_code_apnd * resp_code_apnd) +{ + if (resp_code_apnd->uid_set != NULL) + mailimap_set_free(resp_code_apnd->uid_set); + free(resp_code_apnd); +} + +struct mailimap_uidplus_resp_code_copy * +mailimap_uidplus_resp_code_copy_new(uint32_t uid_uidvalidity, struct mailimap_set * uid_source_set, struct mailimap_set * uid_dest_set) +{ + struct mailimap_uidplus_resp_code_copy * resp_code_copy; + + resp_code_copy = malloc(sizeof(* resp_code_copy)); + if (resp_code_copy == NULL) + return NULL; + + resp_code_copy->uid_uidvalidity = uid_uidvalidity; + resp_code_copy->uid_source_set = uid_source_set; + resp_code_copy->uid_dest_set = uid_dest_set; + + return resp_code_copy; +} + +void mailimap_uidplus_resp_code_copy_free(struct mailimap_uidplus_resp_code_copy * resp_code_copy) +{ + if (resp_code_copy->uid_dest_set != NULL) + mailimap_set_free(resp_code_copy->uid_dest_set); + if (resp_code_copy->uid_source_set != NULL) + mailimap_set_free(resp_code_copy->uid_source_set); + free(resp_code_copy); +} + +void mailimap_uidplus_free(struct mailimap_extension_data * ext_data) +{ + switch (ext_data->ext_type) { + case MAILIMAP_UIDPLUS_RESP_CODE_APND: + mailimap_uidplus_resp_code_apnd_free(ext_data->ext_data); + break; + case MAILIMAP_UIDPLUS_RESP_CODE_COPY: + mailimap_uidplus_resp_code_copy_free(ext_data->ext_data); + break; + case MAILIMAP_UIDPLUS_RESP_CODE_UIDNOTSTICKY: + /* nothing to deallocate */ + break; + } + + free(ext_data); +} + Added: freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imap/uidplus_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,43 @@ +#ifndef UIDPLUS_TYPES_H + +#define UIDPLUS_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <inttypes.h> +#include "mailimap_types.h" + +enum { + MAILIMAP_UIDPLUS_RESP_CODE_APND, + MAILIMAP_UIDPLUS_RESP_CODE_COPY, + MAILIMAP_UIDPLUS_RESP_CODE_UIDNOTSTICKY, +}; + +struct mailimap_uidplus_resp_code_apnd { + uint32_t uid_uidvalidity; + struct mailimap_set * uid_set; +}; + +struct mailimap_uidplus_resp_code_copy { + uint32_t uid_uidvalidity; + struct mailimap_set * uid_source_set; + struct mailimap_set * uid_dest_set; +}; + +struct mailimap_uidplus_resp_code_apnd * +mailimap_uidplus_resp_code_apnd_new(uint32_t uid_uidvalidity, struct mailimap_set * uid_set); +void mailimap_uidplus_resp_code_apnd_free(struct mailimap_uidplus_resp_code_apnd * resp_code_apnd); + +struct mailimap_uidplus_resp_code_copy * +mailimap_uidplus_resp_code_copy_new(uint32_t uid_uidvalidity, struct mailimap_set * uid_source_set, struct mailimap_set * uid_dest_set); +void mailimap_uidplus_resp_code_copy_free(struct mailimap_uidplus_resp_code_copy * resp_code_copy); + +void mailimap_uidplus_free(struct mailimap_extension_data * ext_data); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,12 @@ +top_builddir = ../../.. + +TARGET = libimf +HEADERS = mailimf.h mailimf_types.h mailimf_write_file.h \ + mailimf_types_helper.h \ + mailimf_write_generic.h mailimf_write_mem.h +SOURCES = mailimf.c mailimf_types.c mailimf_write_file.c \ + mailimf_types_helper.c \ + mailimf_write_generic.c mailimf_write_mem.c +INCLUDES = -I$(srcdir)/data-types + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/TODO ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/TODO Wed Dec 20 15:28:56 2006 @@ -0,0 +1,12 @@ +- define a EP_parserstate_s +- remove clist usage +- add a errorcode to string function +- error codes are EP_errornr_s +- prefix everything with EP_ +- mailimf_dot_atom_text_free +- mailimf_address_XX -> _new(void) _init(&addr, ...) _free(addr) +- in fact that data structure should then also contain a + 'dynamically' allocated flag + +- RFC 822 : test the examples +- RFC 2822 : obsolete syntax Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,7602 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf.c,v 1.44 2006/08/05 02:34:07 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimf.h" + +/* + RFC 2822 + + RFC 2821 ... + A message-originating SMTP system SHOULD NOT send a message that + already contains a Return-path header. SMTP servers performing a + relay function MUST NOT inspect the message data, and especially not + to the extent needed to determine if Return-path headers are present. + SMTP servers making final delivery MAY remove Return-path headers + before adding their own. +*/ + +#include <ctype.h> +#include "mmapstring.h" +#include <stdlib.h> +#include <string.h> + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + + + + + + + +static inline int is_dtext(char ch); + +static int mailimf_quoted_pair_parse(const char * message, size_t length, + size_t * index, char * result); + +static int mailimf_ccontent_parse(const char * message, size_t length, + size_t * index); + +static int +mailimf_comment_fws_ccontent_parse(const char * message, size_t length, + size_t * index); + +static inline int mailimf_comment_parse(const char * message, size_t length, + size_t * index); + +static int mailimf_qcontent_parse(const char * message, size_t length, + size_t * index, char * ch); + +static int mailimf_phrase_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_unstructured_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_ignore_unstructured_parse(const char * message, size_t length, + size_t * index); + +static int mailimf_day_of_week_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_day_name_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_date_parse(const char * message, size_t length, + size_t * index, + int * pday, int * pmonth, int * pyear); + +static int mailimf_year_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_month_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_month_name_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_day_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_time_parse(const char * message, size_t length, + size_t * index, + int * phour, int * pmin, + int * psec, + int * zone); +static int mailimf_time_of_day_parse(const char * message, size_t length, + size_t * index, + int * phour, int * pmin, + int * psec); + +static int mailimf_hour_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_minute_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_second_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_zone_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailimf_name_addr_parse(const char * message, size_t length, + size_t * index, + char ** pdisplay_name, + char ** pangle_addr); + +static int mailimf_angle_addr_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_group_parse(const char * message, size_t length, + size_t * index, + struct mailimf_group ** result); + +static int mailimf_display_name_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_addr_spec_parse(const char * message, size_t length, + size_t * index, + char ** address); + +#if 0 +static int mailimf_local_part_parse(const char * message, size_t length, + size_t * index, + char ** result); + +static int mailimf_domain_parse(const char * message, size_t length, + size_t * index, + char ** result); +#endif + +#if 0 +static int mailimf_domain_literal_parse(const char * message, size_t length, + size_t * index, char ** result); +#endif + +#if 0 +static int mailimf_dcontent_parse(const char * message, size_t length, + size_t * index, char * result); +#endif + +static int +mailimf_orig_date_parse(const char * message, size_t length, + size_t * index, struct mailimf_orig_date ** result); + +static int +mailimf_from_parse(const char * message, size_t length, + size_t * index, struct mailimf_from ** result); + +static int +mailimf_sender_parse(const char * message, size_t length, + size_t * index, struct mailimf_sender ** result); + +static int +mailimf_reply_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_reply_to ** result); + +static int +mailimf_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_to ** result); + +static int +mailimf_cc_parse(const char * message, size_t length, + size_t * index, struct mailimf_cc ** result); + +static int +mailimf_bcc_parse(const char * message, size_t length, + size_t * index, struct mailimf_bcc ** result); + +static int mailimf_message_id_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message_id ** result); + +static int +mailimf_in_reply_to_parse(const char * message, size_t length, + size_t * index, + struct mailimf_in_reply_to ** result); + +#if 0 +static int mailimf_references_parse(const char * message, size_t length, + size_t * index, + struct mailimf_references ** + result); +#endif + +static int mailimf_unstrict_msg_id_parse(const char * message, size_t length, + size_t * index, + char ** result); + +#if 0 +static int mailimf_id_left_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_id_right_parse(const char * message, size_t length, + size_t * index, char ** result); +#endif + +#if 0 +static int mailimf_no_fold_quote_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int mailimf_no_fold_literal_parse(const char * message, size_t length, + size_t * index, char ** result); +#endif + +static int mailimf_subject_parse(const char * message, size_t length, + size_t * index, + struct mailimf_subject ** result); + +static int mailimf_comments_parse(const char * message, size_t length, + size_t * index, + struct mailimf_comments ** result); + +static int mailimf_keywords_parse(const char * message, size_t length, + size_t * index, + struct mailimf_keywords ** result); + +static int +mailimf_resent_date_parse(const char * message, size_t length, + size_t * index, struct mailimf_orig_date ** result); + +static int +mailimf_resent_from_parse(const char * message, size_t length, + size_t * index, struct mailimf_from ** result); + +static int +mailimf_resent_sender_parse(const char * message, size_t length, + size_t * index, struct mailimf_sender ** result); + +static int +mailimf_resent_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_to ** result); + +static int +mailimf_resent_cc_parse(const char * message, size_t length, + size_t * index, struct mailimf_cc ** result); + +static int +mailimf_resent_bcc_parse(const char * message, size_t length, + size_t * index, struct mailimf_bcc ** result); + +static int +mailimf_resent_msg_id_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message_id ** result); + +static int mailimf_return_parse(const char * message, size_t length, + size_t * index, + struct mailimf_return ** result); + +static int +mailimf_path_parse(const char * message, size_t length, + size_t * index, struct mailimf_path ** result); + +static int +mailimf_optional_field_parse(const char * message, size_t length, + size_t * index, + struct mailimf_optional_field ** result); + +static int mailimf_field_name_parse(const char * message, size_t length, + size_t * index, char ** result); + + + + + + + + + + + + + + + + + + + + + + + + + +/* *************************************************************** */ + +static inline int is_digit(char ch) +{ + return (ch >= '0') && (ch <= '9'); +} + +static int mailimf_digit_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_digit(message[cur_token])) { + * result = message[cur_token] - '0'; + cur_token ++; + * index = cur_token; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + +int +mailimf_number_parse(const char * message, size_t length, + size_t * index, uint32_t * result) +{ + size_t cur_token; + int digit; + uint32_t number; + int parsed; + int r; + + cur_token = * index; + parsed = FALSE; + + number = 0; + while (1) { + r = mailimf_digit_parse(message, length, &cur_token, &digit); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + number *= 10; + number += digit; + parsed = TRUE; + } + + if (!parsed) + return MAILIMF_ERROR_PARSE; + + * result = number; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +int mailimf_char_parse(const char * message, size_t length, + size_t * index, char token) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (message[cur_token] == token) { + cur_token ++; + * index = cur_token; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + +int mailimf_unstrict_char_parse(const char * message, size_t length, + size_t * index, char token) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_char_parse(message, length, &cur_token, token); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +int +mailimf_token_case_insensitive_len_parse(const char * message, size_t length, + size_t * index, char * token, + size_t token_length) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token + token_length - 1 >= length) + return MAILIMF_ERROR_PARSE; + + if (strncasecmp(message + cur_token, token, token_length) == 0) { + cur_token += token_length; + * index = cur_token; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + +static int mailimf_oparenth_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_char_parse(message, length, index, '('); +} + +static int mailimf_cparenth_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_char_parse(message, length, index, ')'); +} + +static int mailimf_comma_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, ','); +} + +static int mailimf_dquote_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_char_parse(message, length, index, '\"'); +} + +static int mailimf_colon_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, ':'); +} + +static int mailimf_semi_colon_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, ';'); +} + +static int mailimf_plus_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '+'); +} + +static int mailimf_minus_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '-'); +} + +static int mailimf_lower_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '<'); +} + +static int mailimf_greater_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '>'); +} + +#if 0 +static int mailimf_obracket_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '['); +} + +static int mailimf_cbracket_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, ']'); +} +#endif + +static int mailimf_at_sign_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '@'); +} + +static int mailimf_point_parse(const char * message, size_t length, + size_t * index) +{ + return mailimf_unstrict_char_parse(message, length, index, '.'); +} + +int +mailimf_custom_string_parse(const char * message, size_t length, + size_t * index, char ** result, + int (* is_custom_char)(char)) +{ + size_t begin; + size_t end; + char * gstr; + + begin = * index; + + end = begin; + + if (end >= length) + return MAILIMF_ERROR_PARSE; + + while (is_custom_char(message[end])) { + end ++; + if (end >= length) + break; + } + + if (end != begin) { + /* + gstr = strndup(message + begin, end - begin); + */ + gstr = malloc(end - begin + 1); + if (gstr == NULL) + return MAILIMF_ERROR_MEMORY; + strncpy(gstr, message + begin, end - begin); + gstr[end - begin] = '\0'; + + * index = end; + * result = gstr; + return MAILIMF_NO_ERROR; + } + else + return MAILIMF_ERROR_PARSE; +} + + + + + + + +typedef int mailimf_struct_parser(const char * message, size_t length, + size_t * index, void * result); + +typedef int mailimf_struct_destructor(void * result); + + +static int +mailimf_struct_multiple_parse(const char * message, size_t length, + size_t * index, clist ** result, + mailimf_struct_parser * parser, + mailimf_struct_destructor * destructor) +{ + clist * struct_list; + size_t cur_token; + void * value; + int r; + int res; + + cur_token = * index; + + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + while (1) { + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + r = clist_append(struct_list, value); + if (r < 0) { + (* destructor)(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + * result = struct_list; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); + err: + return res; +} + + + +static int +mailimf_struct_list_parse(const char * message, size_t length, + size_t * index, clist ** result, + char symbol, + mailimf_struct_parser * parser, + mailimf_struct_destructor * destructor) +{ + clist * struct_list; + size_t cur_token; + void * value; + size_t final_token; + int r; + int res; + + cur_token = * index; + + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + struct_list = clist_new(); + if (struct_list == NULL) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + final_token = cur_token; + + while (1) { + r = mailimf_unstrict_char_parse(message, length, &cur_token, symbol); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + + r = parser(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + + r = clist_append(struct_list, value); + if (r < 0) { + destructor(value); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + final_token = cur_token; + } + + * result = struct_list; + * index = final_token; + + return MAILIMF_NO_ERROR; + + free: + clist_foreach(struct_list, (clist_func) destructor, NULL); + clist_free(struct_list); + err: + return res; +} + +static inline int mailimf_wsp_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if ((message[cur_token] != ' ') && (message[cur_token] != '\t')) + return MAILIMF_ERROR_PARSE; + + cur_token ++; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + + +int mailimf_crlf_parse(const char * message, size_t length, size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_char_parse(message, length, &cur_token, '\r'); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_char_parse(message, length, &cur_token, '\n'); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + return MAILIMF_NO_ERROR; +} + +static int mailimf_unstrict_crlf_parse(const char * message, + size_t length, size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + mailimf_cfws_parse(message, length, &cur_token); + + r = mailimf_char_parse(message, length, &cur_token, '\r'); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_char_parse(message, length, &cur_token, '\n'); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + return MAILIMF_NO_ERROR; +} + +/* ************************************************************************ */ + + + +/* RFC 2822 grammar */ + +/* +NO-WS-CTL = %d1-8 / ; US-ASCII control characters + %d11 / ; that do not include the + %d12 / ; carriage return, line feed, + %d14-31 / ; and white space characters + %d127 +*/ + +static inline int is_no_ws_ctl(char ch) +{ + if ((ch == 9) || (ch == 10) || (ch == 13)) + return FALSE; + + if (ch == 127) + return TRUE; + + return (ch >= 1) && (ch <= 31); +} + +/* +text = %d1-9 / ; Characters excluding CR and LF + %d11 / + %d12 / + %d14-127 / + obs-text +*/ + +/* +specials = "(" / ")" / ; Special characters used in + "<" / ">" / ; other parts of the syntax + "[" / "]" / + ":" / ";" / + "@" / "\" / + "," / "." / + DQUOTE +*/ + +/* +quoted-pair = ("\" text) / obs-qp +*/ + +static inline int mailimf_quoted_pair_parse(const char * message, size_t length, + size_t * index, char * result) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token + 1 >= length) + return MAILIMF_ERROR_PARSE; + + if (message[cur_token] != '\\') + return MAILIMF_ERROR_PARSE; + + cur_token ++; + * result = message[cur_token]; + cur_token ++; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space + obs-FWS +*/ + +int mailimf_fws_parse(const char * message, size_t length, size_t * index) +{ + size_t cur_token; + size_t final_token; + int fws_1; + int fws_2; + int fws_3; + int r; + + cur_token = * index; + + fws_1 = FALSE; + while (1) { + r = mailimf_wsp_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + fws_1 = TRUE; + } + final_token = cur_token; + + r = mailimf_crlf_parse(message, length, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + fws_2 = TRUE; + break; + case MAILIMF_ERROR_PARSE: + fws_2 = FALSE; + break; + default: + return r; + } + + fws_3 = FALSE; + if (fws_2) { + while (1) { + r = mailimf_wsp_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + fws_3 = TRUE; + } + } + + if ((!fws_1) && (!fws_3)) + return MAILIMF_ERROR_PARSE; + + if (!fws_3) + cur_token = final_token; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + + +/* +ctext = NO-WS-CTL / ; Non white space controls + + %d33-39 / ; The rest of the US-ASCII + %d42-91 / ; characters not including "(", + %d93-126 ; ")", or "\" +*/ + +static inline int is_ctext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (is_no_ws_ctl(ch)) + return TRUE; + + if (uch < 33) + return FALSE; + + if ((uch == 40) || (uch == 41)) + return FALSE; + + if (uch == 92) + return FALSE; + + if (uch == 127) + return FALSE; + + return TRUE; +} + +/* +ccontent = ctext / quoted-pair / comment +*/ + +static inline int mailimf_ccontent_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_ctext(message[cur_token])) { + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_comment_parse(message, length, &cur_token); + + if (r == MAILIMF_ERROR_PARSE) + return r; + } + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +[FWS] ccontent +*/ + +static inline int +mailimf_comment_fws_ccontent_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_ccontent_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +comment = "(" *([FWS] ccontent) [FWS] ")" +*/ + +static inline int mailimf_comment_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_oparenth_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + while (1) { + r = mailimf_comment_fws_ccontent_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + } + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_cparenth_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +[FWS] comment +*/ + +static inline int mailimf_cfws_fws_comment_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_comment_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +CFWS = *([FWS] comment) (([FWS] comment) / FWS) +*/ + +int mailimf_cfws_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int has_comment; + int r; + + cur_token = * index; + + has_comment = FALSE; + while (1) { + r = mailimf_cfws_fws_comment_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + has_comment = TRUE; + } + + if (!has_comment) { + r = mailimf_fws_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + } + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +atext = ALPHA / DIGIT / ; Any character except controls, + "!" / "#" / ; SP, and specials. + "$" / "%" / ; Used for atoms + "&" / "'" / + "*" / "+" / + "-" / "/" / + "=" / "?" / + "^" / "_" / + "`" / "{" / + "|" / "}" / + "~" +*/ + +static inline int is_atext(char ch) +{ + switch (ch) { + case ' ': + case '\t': + case '\n': + case '\r': +#if 0 + case '(': + case ')': +#endif + case '<': + case '>': +#if 0 + case '@': +#endif + case ',': + case '"': + case ':': + case ';': + return FALSE; + default: + return TRUE; + } +} + +/* +atom = [CFWS] 1*atext [CFWS] +*/ + +int mailimf_atom_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + int r; + int res; + char * atom; + size_t end; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + end = cur_token; + if (end >= length) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + while (is_atext(message[end])) { + end ++; + if (end >= length) + break; + } + if (end == cur_token) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + atom = malloc(end - cur_token + 1); + if (atom == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + strncpy(atom, message + cur_token, end - cur_token); + atom[end - cur_token] = '\0'; + + cur_token = end; + + * index = cur_token; + * result = atom; + + return MAILIMF_NO_ERROR; + + err: + return res; +} + +int mailimf_fws_atom_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + int r; + int res; + char * atom; + size_t end; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + end = cur_token; + if (end >= length) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + while (is_atext(message[end])) { + end ++; + if (end >= length) + break; + } + if (end == cur_token) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + atom = malloc(end - cur_token + 1); + if (atom == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + strncpy(atom, message + cur_token, end - cur_token); + atom[end - cur_token] = '\0'; + + cur_token = end; + + * index = cur_token; + * result = atom; + + return MAILIMF_NO_ERROR; + + err: + return res; +} + +/* +dot-atom = [CFWS] dot-atom-text [CFWS] +*/ + +#if 0 +static int mailimf_dot_atom_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_atom_parse(message, length, index, result); +} +#endif + +/* +dot-atom-text = 1*atext *("." 1*atext) +*/ + +#if 0 +static int +mailimf_dot_atom_text_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_atom_parse(message, length, index, result); +} +#endif + +/* +qtext = NO-WS-CTL / ; Non white space controls + + %d33 / ; The rest of the US-ASCII + %d35-91 / ; characters not including "\" + %d93-126 ; or the quote character +*/ + +static inline int is_qtext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (is_no_ws_ctl(ch)) + return TRUE; + + if (uch < 33) + return FALSE; + + if (uch == 34) + return FALSE; + + if (uch == 92) + return FALSE; + + if (uch == 127) + return FALSE; + + return TRUE; +} + +/* +qcontent = qtext / quoted-pair +*/ + +static int mailimf_qcontent_parse(const char * message, size_t length, + size_t * index, char * result) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_qtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * result = ch; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +quoted-string = [CFWS] + DQUOTE *([FWS] qcontent) [FWS] DQUOTE + [CFWS] +*/ + +int mailimf_quoted_string_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + MMAPString * gstr; + char ch; + char * str; + int r; + int res; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + gstr = mmap_string_new(""); + if (gstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + while (1) { + r = mailimf_fws_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ' ') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r != MAILIMF_ERROR_PARSE) { + res = r; + goto free_gstr; + } + + r = mailimf_qcontent_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ch) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free_gstr; + } + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_gstr; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + str = strdup(gstr->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + mmap_string_free(gstr); + + * index = cur_token; + * result = str; + + return MAILIMF_NO_ERROR; + + free_gstr: + mmap_string_free(gstr); + err: + return res; +} + +int mailimf_fws_quoted_string_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + MMAPString * gstr; + char ch; + char * str; + int r; + int res; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + gstr = mmap_string_new(""); + if (gstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + while (1) { + r = mailimf_fws_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ' ') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r != MAILIMF_ERROR_PARSE) { + res = r; + goto free_gstr; + } + + r = mailimf_qcontent_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + if (mmap_string_append_c(gstr, ch) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free_gstr; + } + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_gstr; + } + +#if 0 + if (mmap_string_append_c(gstr, '\"') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } +#endif + + str = strdup(gstr->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_gstr; + } + mmap_string_free(gstr); + + * index = cur_token; + * result = str; + + return MAILIMF_NO_ERROR; + + free_gstr: + mmap_string_free(gstr); + err: + return res; +} + +/* +word = atom / quoted-string +*/ + +int mailimf_word_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + char * word; + int r; + + cur_token = * index; + + r = mailimf_atom_parse(message, length, &cur_token, &word); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_quoted_string_parse(message, length, &cur_token, &word); + + if (r != MAILIMF_NO_ERROR) + return r; + + * result = word; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +int mailimf_fws_word_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + char * word; + int r; + + cur_token = * index; + + r = mailimf_fws_atom_parse(message, length, &cur_token, &word); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_fws_quoted_string_parse(message, length, &cur_token, &word); + + if (r != MAILIMF_NO_ERROR) + return r; + + * result = word; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +phrase = 1*word / obs-phrase +*/ + +static int mailimf_phrase_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + MMAPString * gphrase; + char * word; + int first; + size_t cur_token; + int r; + int res; + char * str; + + cur_token = * index; + + gphrase = mmap_string_new(""); + if (gphrase == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + first = TRUE; + + while (1) { + r = mailimf_fws_word_parse(message, length, &cur_token, &word); + if (r == MAILIMF_NO_ERROR) { + if (!first) { + if (mmap_string_append_c(gphrase, ' ') == NULL) { + mailimf_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + if (mmap_string_append(gphrase, word) == NULL) { + mailimf_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + mailimf_word_free(word); + first = FALSE; + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free; + } + } + + if (first) { + res = MAILIMF_ERROR_PARSE; + goto free; + } + + str = strdup(gphrase->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + mmap_string_free(gphrase); + + * result = str; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(gphrase); + err: + return res; +} + +/* +utext = NO-WS-CTL / ; Non white space controls + %d33-126 / ; The rest of US-ASCII + obs-utext + +added : WSP +*/ + +enum { + UNSTRUCTURED_START, + UNSTRUCTURED_CR, + UNSTRUCTURED_LF, + UNSTRUCTURED_WSP, + UNSTRUCTURED_OUT +}; + +static int mailimf_unstructured_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + int state; + size_t begin; + size_t terminal; + char * str; + + cur_token = * index; + + + while (1) { + int r; + + r = mailimf_wsp_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + return r; + } + } + + state = UNSTRUCTURED_START; + begin = cur_token; + terminal = cur_token; + + while (state != UNSTRUCTURED_OUT) { + + switch(state) { + case UNSTRUCTURED_START: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + terminal = cur_token; + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_CR: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + + case UNSTRUCTURED_LF: + if (cur_token >= length) { + state = UNSTRUCTURED_OUT; + break; + } + + switch(message[cur_token]) { + case '\t': + case ' ': + state = UNSTRUCTURED_WSP; + break; + default: + state = UNSTRUCTURED_OUT; + break; + } + break; + case UNSTRUCTURED_WSP: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + } + + cur_token ++; + } + + str = malloc(terminal - begin + 1); + if (str == NULL) + return MAILIMF_ERROR_MEMORY; + strncpy(str, message + begin, terminal - begin); + str[terminal - begin] = '\0'; + + * index = terminal; + * result = str; + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_ignore_unstructured_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int state; + size_t terminal; + + cur_token = * index; + + state = UNSTRUCTURED_START; + terminal = cur_token; + + while (state != UNSTRUCTURED_OUT) { + + switch(state) { + case UNSTRUCTURED_START: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + terminal = cur_token; + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_CR: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + switch(message[cur_token]) { + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_LF: + if (cur_token >= length) { + state = UNSTRUCTURED_OUT; + break; + } + switch(message[cur_token]) { + case '\t': + case ' ': + state = UNSTRUCTURED_WSP; + break; + default: + state = UNSTRUCTURED_OUT; + break; + } + break; + case UNSTRUCTURED_WSP: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + } + + cur_token ++; + } + + * index = terminal; + + return MAILIMF_NO_ERROR; +} + + +int mailimf_ignore_field_parse(const char * message, size_t length, + size_t * index) +{ + int has_field; + size_t cur_token; + int state; + size_t terminal; + + has_field = FALSE; + cur_token = * index; + + terminal = cur_token; + state = UNSTRUCTURED_START; + + /* check if this is not a beginning CRLF */ + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (message[cur_token]) { + case '\r': + return MAILIMF_ERROR_PARSE; + case '\n': + return MAILIMF_ERROR_PARSE; + } + + while (state != UNSTRUCTURED_OUT) { + + switch(state) { + case UNSTRUCTURED_START: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + case ':': + has_field = TRUE; + state = UNSTRUCTURED_START; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_CR: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\n': + state = UNSTRUCTURED_LF; + break; + case ':': + has_field = TRUE; + state = UNSTRUCTURED_START; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + case UNSTRUCTURED_LF: + if (cur_token >= length) { + terminal = cur_token; + state = UNSTRUCTURED_OUT; + break; + } + + switch(message[cur_token]) { + case '\t': + case ' ': + state = UNSTRUCTURED_WSP; + break; + default: + terminal = cur_token; + state = UNSTRUCTURED_OUT; + break; + } + break; + case UNSTRUCTURED_WSP: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(message[cur_token]) { + case '\r': + state = UNSTRUCTURED_CR; + break; + case '\n': + state = UNSTRUCTURED_LF; + break; + case ':': + has_field = TRUE; + state = UNSTRUCTURED_START; + break; + default: + state = UNSTRUCTURED_START; + break; + } + break; + } + + cur_token ++; + } + + if (!has_field) + return MAILIMF_ERROR_PARSE; + + * index = terminal; + + return MAILIMF_NO_ERROR; +} + + +/* +date-time = [ day-of-week "," ] date FWS time [CFWS] +*/ + +int mailimf_date_time_parse(const char * message, size_t length, + size_t * index, + struct mailimf_date_time ** result) +{ + size_t cur_token; + int day_of_week; + struct mailimf_date_time * date_time; + int day; + int month; + int year; + int hour; + int min; + int sec; + int zone; + int r; + + cur_token = * index; + + day_of_week = -1; + r = mailimf_day_of_week_parse(message, length, &cur_token, &day_of_week); + if (r == MAILIMF_NO_ERROR) { + r = mailimf_comma_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + } + else if (r != MAILIMF_ERROR_PARSE) + return r; + + day = 0; + month = 0; + year = 0; + r = mailimf_date_parse(message, length, &cur_token, &day, &month, &year); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_fws_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + hour = 0; + min = 0; + sec = 0; + zone = 0; + r = mailimf_time_parse(message, length, &cur_token, + &hour, &min, &sec, &zone); + if (r != MAILIMF_NO_ERROR) + return r; + + date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone); + if (date_time == NULL) + return MAILIMF_ERROR_MEMORY; + + * index = cur_token; + * result = date_time; + + return MAILIMF_NO_ERROR; +} + +/* +day-of-week = ([FWS] day-name) / obs-day-of-week +*/ + +static int mailimf_day_of_week_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + int day_of_week; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_day_name_parse(message, length, &cur_token, &day_of_week); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = day_of_week; + + return MAILIMF_NO_ERROR; +} + +/* +day-name = "Mon" / "Tue" / "Wed" / "Thu" / + "Fri" / "Sat" / "Sun" +*/ + +struct mailimf_token_value { + int value; + char * str; +}; + +static struct mailimf_token_value day_names[] = { + {1, "Mon"}, + {2, "Tue"}, + {3, "Wed"}, + {4, "Thu"}, + {5, "Fri"}, + {6, "Sat"}, + {7, "Sun"}, +}; + +enum { + DAY_NAME_START, + DAY_NAME_T, + DAY_NAME_S +}; + +static int guess_day_name(const char * message, size_t length, size_t index) +{ + int state; + + state = DAY_NAME_START; + + while (1) { + + if (index >= length) + return -1; + + switch(state) { + case DAY_NAME_START: + switch((char) toupper((unsigned char) message[index])) { + case 'M': /* Mon */ + return 1; + break; + case 'T': /* Tue Thu */ + state = DAY_NAME_T; + break; + case 'W': /* Wed */ + return 3; + case 'F': + return 5; + case 'S': /* Sat Sun */ + state = DAY_NAME_S; + break; + default: + return -1; + } + break; + case DAY_NAME_T: + switch((char) toupper((unsigned char) message[index])) { + case 'U': + return 2; + case 'H': + return 4; + default: + return -1; + } + break; + case DAY_NAME_S: + switch((char) toupper((unsigned char) message[index])) { + case 'A': + return 6; + case 'U': + return 7; + default: + return -1; + } + break; + } + + index ++; + } +} + +static int mailimf_day_name_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + int day_of_week; + int guessed_day; + int r; + + cur_token = * index; + + guessed_day = guess_day_name(message, length, cur_token); + if (guessed_day == -1) + return MAILIMF_ERROR_PARSE; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, + day_names[guessed_day - 1].str); + if (r != MAILIMF_NO_ERROR) + return r; + + day_of_week = guessed_day; + + * result = day_of_week; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +date = day month year +*/ + +static int mailimf_date_parse(const char * message, size_t length, + size_t * index, + int * pday, int * pmonth, int * pyear) +{ + size_t cur_token; + int day; + int month; + int year; + int r; + + cur_token = * index; + + day = 1; + r = mailimf_day_parse(message, length, &cur_token, &day); + if (r != MAILIMF_NO_ERROR) + return r; + + month = 1; + r = mailimf_month_parse(message, length, &cur_token, &month); + if (r != MAILIMF_NO_ERROR) + return r; + + year = 2001; + r = mailimf_year_parse(message, length, &cur_token, &year); + if (r != MAILIMF_NO_ERROR) + return r; + + * pday = day; + * pmonth = month; + * pyear = year; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +year = 4*DIGIT / obs-year +*/ + +static int mailimf_year_parse(const char * message, size_t length, + size_t * index, int * result) +{ + uint32_t number; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &number); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = number; + + return MAILIMF_NO_ERROR; +} + +/* +month = (FWS month-name FWS) / obs-month +*/ + +static int mailimf_month_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + int month; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_month_name_parse(message, length, &cur_token, &month); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = month; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +month-name = "Jan" / "Feb" / "Mar" / "Apr" / + "May" / "Jun" / "Jul" / "Aug" / + "Sep" / "Oct" / "Nov" / "Dec" +*/ + +static struct mailimf_token_value month_names[] = { + {1, "Jan"}, + {2, "Feb"}, + {3, "Mar"}, + {4, "Apr"}, + {5, "May"}, + {6, "Jun"}, + {7, "Jul"}, + {8, "Aug"}, + {9, "Sep"}, + {10, "Oct"}, + {11, "Nov"}, + {12, "Dec"}, +}; + +enum { + MONTH_START, + MONTH_J, + MONTH_JU, + MONTH_M, + MONTH_MA, + MONTH_A +}; + +static int guess_month(const char * message, size_t length, size_t index) +{ + int state; + + state = MONTH_START; + + while (1) { + + if (index >= length) + return -1; + + switch(state) { + case MONTH_START: + switch((char) toupper((unsigned char) message[index])) { + case 'J': /* Jan Jun Jul */ + state = MONTH_J; + break; + case 'F': /* Feb */ + return 2; + case 'M': /* Mar May */ + state = MONTH_M; + break; + case 'A': /* Apr Aug */ + state = MONTH_A; + break; + case 'S': /* Sep */ + return 9; + case 'O': /* Oct */ + return 10; + case 'N': /* Nov */ + return 11; + case 'D': /* Dec */ + return 12; + default: + return -1; + } + break; + case MONTH_J: + switch((char) toupper((unsigned char) message[index])) { + case 'A': + return 1; + case 'U': + state = MONTH_JU; + break; + default: + return -1; + } + break; + case MONTH_JU: + switch((char) toupper((unsigned char) message[index])) { + case 'N': + return 6; + case 'L': + return 7; + default: + return -1; + } + break; + case MONTH_M: + switch((char) toupper((unsigned char) message[index])) { + case 'A': + state = MONTH_MA; + break; + default: + return -1; + } + break; + case MONTH_MA: + switch((char) toupper((unsigned char) message[index])) { + case 'Y': + return 5; + case 'R': + return 3; + default: + return -1; + } + break; + case MONTH_A: + switch((char) toupper((unsigned char) message[index])) { + case 'P': + return 4; + case 'U': + return 8; + default: + return -1; + } + break; + } + + index ++; + } +} + +static int mailimf_month_name_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + int month; + int guessed_month; + int r; + + cur_token = * index; + + guessed_month = guess_month(message, length, cur_token); + if (guessed_month == -1) + return MAILIMF_ERROR_PARSE; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, + month_names[guessed_month - 1].str); + if (r != MAILIMF_NO_ERROR) + return r; + + month = guessed_month; + + * result = month; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +day = ([FWS] 1*2DIGIT) / obs-day +*/ + +static int mailimf_day_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + uint32_t day; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &day); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = day; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +time = time-of-day FWS zone +*/ + +static int mailimf_time_parse(const char * message, size_t length, + size_t * index, + int * phour, int * pmin, + int * psec, + int * pzone) +{ + size_t cur_token; + int hour; + int min; + int sec; + int zone; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_time_of_day_parse(message, length, &cur_token, + &hour, &min, &sec); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_zone_parse(message, length, &cur_token, &zone); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + zone = 0; + } + else { + return r; + } + + * phour = hour; + * pmin = min; + * psec = sec; + * pzone = zone; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +time-of-day = hour ":" minute [ ":" second ] +*/ + +static int mailimf_time_of_day_parse(const char * message, size_t length, + size_t * index, + int * phour, int * pmin, + int * psec) +{ + int hour; + int min; + int sec; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_hour_parse(message, length, &cur_token, &hour); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_minute_parse(message, length, &cur_token, &min); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_colon_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + r = mailimf_second_parse(message, length, &cur_token, &sec); + if (r != MAILIMF_NO_ERROR) + return r; + } + else if (r == MAILIMF_ERROR_PARSE) + sec = 0; + else + return r; + + * phour = hour; + * pmin = min; + * psec = sec; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +hour = 2DIGIT / obs-hour +*/ + +static int mailimf_hour_parse(const char * message, size_t length, + size_t * index, int * result) +{ + uint32_t hour; + int r; + + r = mailimf_number_parse(message, length, index, &hour); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = hour; + + return MAILIMF_NO_ERROR; +} + +/* +minute = 2DIGIT / obs-minute +*/ + +static int mailimf_minute_parse(const char * message, size_t length, + size_t * index, int * result) +{ + uint32_t minute; + int r; + + r = mailimf_number_parse(message, length, index, &minute); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = minute; + + return MAILIMF_NO_ERROR; +} + +/* +second = 2DIGIT / obs-second +*/ + +static int mailimf_second_parse(const char * message, size_t length, + size_t * index, int * result) +{ + uint32_t second; + int r; + + r = mailimf_number_parse(message, length, index, &second); + if (r != MAILIMF_NO_ERROR) + return r; + + * result = second; + + return MAILIMF_NO_ERROR; +} + +/* +zone = (( "+" / "-" ) 4DIGIT) / obs-zone +*/ + +/* +obs-zone = "UT" / "GMT" / ; Universal Time + ; North American UT + ; offsets + "EST" / "EDT" / ; Eastern: - 5/ - 4 + "CST" / "CDT" / ; Central: - 6/ - 5 + "MST" / "MDT" / ; Mountain: - 7/ - 6 + "PST" / "PDT" / ; Pacific: - 8/ - 7 + + %d65-73 / ; Military zones - "A" + %d75-90 / ; through "I" and "K" + %d97-105 / ; through "Z", both + %d107-122 ; upper and lower case +*/ + +enum { + STATE_ZONE_1 = 0, + STATE_ZONE_2 = 1, + STATE_ZONE_3 = 2, + STATE_ZONE_OK = 3, + STATE_ZONE_ERR = 4, + STATE_ZONE_CONT = 5 +}; + +static int mailimf_zone_parse(const char * message, size_t length, + size_t * index, int * result) +{ + uint32_t zone; + int sign; + size_t cur_token; + int r; + + cur_token = * index; + + if (cur_token + 1 < length) { + if ((message[cur_token] == 'U') && (message[cur_token] == 'T')) { + * result = TRUE; + * index = cur_token + 2; + + return MAILIMF_NO_ERROR; + } + } + + if (cur_token + 2 < length) { + int state; + + state = STATE_ZONE_1; + + while (state <= 2) { + switch (state) { + case STATE_ZONE_1: + switch (message[cur_token]) { + case 'G': + if (message[cur_token + 1] == 'M' && message[cur_token + 2] == 'T') { + zone = 0; + state = STATE_ZONE_OK; + } + else { + state = STATE_ZONE_ERR; + } + break; + case 'E': + zone = -5; + state = STATE_ZONE_2; + break; + case 'C': + zone = -6; + state = STATE_ZONE_2; + break; + case 'M': + zone = -7; + state = STATE_ZONE_2; + break; + case 'P': + zone = -8; + state = STATE_ZONE_2; + break; + default: + state = STATE_ZONE_CONT; + break; + } + break; + case STATE_ZONE_2: + switch (message[cur_token + 1]) { + case 'S': + state = STATE_ZONE_3; + break; + case 'D': + zone ++; + state = STATE_ZONE_3; + break; + default: + state = STATE_ZONE_ERR; + break; + } + break; + case STATE_ZONE_3: + if (message[cur_token + 2] == 'T') { + zone *= 100; + state = STATE_ZONE_OK; + } + else + state = STATE_ZONE_ERR; + break; + } + } + + switch (state) { + case STATE_ZONE_OK: + * result = zone; + * index = cur_token + 3; + return MAILIMF_NO_ERROR; + + case STATE_ZONE_ERR: + return MAILIMF_ERROR_PARSE; + } + } + + sign = 1; + r = mailimf_plus_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + sign = 1; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_minus_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + sign = -1; + } + + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + sign = 1; + else + return r; + + r = mailimf_number_parse(message, length, &cur_token, &zone); + if (r != MAILIMF_NO_ERROR) + return r; + + zone = zone * sign; + + * index = cur_token; + * result = zone; + + return MAILIMF_NO_ERROR; +} + +/* +address = mailbox / group +*/ + +int mailimf_address_parse(const char * message, size_t length, + size_t * index, + struct mailimf_address ** result) +{ + int type; + size_t cur_token; + struct mailimf_mailbox * mailbox; + struct mailimf_group * group; + struct mailimf_address * address; + int r; + int res; + + cur_token = * index; + + mailbox = NULL; + group = NULL; + + type = MAILIMF_ADDRESS_ERROR; /* XXX - removes a gcc warning */ + r = mailimf_group_parse(message, length, &cur_token, &group); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ADDRESS_GROUP; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_mailbox_parse(message, length, &cur_token, &mailbox); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ADDRESS_MAILBOX; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + address = mailimf_address_new(type, mailbox, group); + if (address == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = address; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (mailbox != NULL) + mailimf_mailbox_free(mailbox); + if (group != NULL) + mailimf_group_free(group); + err: + return res; +} + + +/* +mailbox = name-addr / addr-spec +*/ + + +int mailimf_mailbox_parse(const char * message, size_t length, + size_t * index, + struct mailimf_mailbox ** result) +{ + size_t cur_token; + char * display_name; + struct mailimf_mailbox * mailbox; + char * addr_spec; + int r; + int res; + + cur_token = * index; + display_name = NULL; + addr_spec = NULL; + + r = mailimf_name_addr_parse(message, length, &cur_token, + &display_name, &addr_spec); + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mailbox = mailimf_mailbox_new(display_name, addr_spec); + if (mailbox == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mailbox; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (display_name != NULL) + mailimf_display_name_free(display_name); + if (addr_spec != NULL) + mailimf_addr_spec_free(addr_spec); + err: + return res; +} + +/* +name-addr = [display-name] angle-addr +*/ + +static int mailimf_name_addr_parse(const char * message, size_t length, + size_t * index, + char ** pdisplay_name, + char ** pangle_addr) +{ + char * display_name; + char * angle_addr; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + display_name = NULL; + angle_addr = NULL; + + r = mailimf_display_name_parse(message, length, &cur_token, &display_name); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_angle_addr_parse(message, length, &cur_token, &angle_addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_display_name; + } + + * pdisplay_name = display_name; + * pangle_addr = angle_addr; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_display_name: + if (display_name != NULL) + mailimf_display_name_free(display_name); + err: + return res; +} + +/* +angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr +*/ + +static int mailimf_angle_addr_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + char * addr_spec; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_lower_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + free(addr_spec); + return r; + } + + * result = addr_spec; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +group = display-name ":" [mailbox-list / CFWS] ";" + [CFWS] +*/ + +static int mailimf_group_parse(const char * message, size_t length, + size_t * index, + struct mailimf_group ** result) +{ + size_t cur_token; + char * display_name; + struct mailimf_mailbox_list * mailbox_list; + struct mailimf_group * group; + int r; + int res; + + cur_token = * index; + + mailbox_list = NULL; + + r = mailimf_display_name_parse(message, length, &cur_token, &display_name); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_display_name; + } + + r = mailimf_mailbox_list_parse(message, length, &cur_token, &mailbox_list); + switch (r) { + case MAILIMF_NO_ERROR: + break; + case MAILIMF_ERROR_PARSE: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + break; + default: + return r; + } + + r = mailimf_semi_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mailbox_list; + } + + group = mailimf_group_new(display_name, mailbox_list); + if (group == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mailbox_list; + } + + * index = cur_token; + * result = group; + + return MAILIMF_NO_ERROR; + + free_mailbox_list: + mailimf_mailbox_list_free(mailbox_list); + free_display_name: + mailimf_display_name_free(display_name); + err: + return res; +} + +/* +display-name = phrase +*/ + +static int mailimf_display_name_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_phrase_parse(message, length, index, result); +} + +/* +mailbox-list = (mailbox *("," mailbox)) / obs-mbox-list +*/ + +int +mailimf_mailbox_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_mailbox_list ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_mailbox_list * mailbox_list; + int r; + int res; + + cur_token = * index; + + r = mailimf_struct_list_parse(message, length, + &cur_token, &list, ',', + (mailimf_struct_parser *) + mailimf_mailbox_parse, + (mailimf_struct_destructor *) + mailimf_mailbox_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mailbox_list = mailimf_mailbox_list_new(list); + if (mailbox_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = mailbox_list; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(list); + err: + return res; +} + +/* +address-list = (address *("," address)) / obs-addr-list +*/ + + +int +mailimf_address_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_address_list ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_address_list * address_list; + int r; + int res; + + cur_token = * index; + + r = mailimf_struct_list_parse(message, length, + &cur_token, &list, ',', + (mailimf_struct_parser *) + mailimf_address_parse, + (mailimf_struct_destructor *) + mailimf_address_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + address_list = mailimf_address_list_new(list); + if (address_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = address_list; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_address_free, NULL); + clist_free(list); + err: + return res; +} + +/* +addr-spec = local-part "@" domain +*/ + + +static int mailimf_addr_spec_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + size_t cur_token; +#if 0 + char * local_part; + char * domain; +#endif + char * addr_spec; + int r; + int res; + size_t begin; + size_t end; + int final; + size_t count; + const char * src; + char * dest; + size_t i; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + end = cur_token; + if (end >= length) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + begin = cur_token; + + final = FALSE; + while (1) { + switch (message[end]) { + case '>': + case ',': + case '\r': + case '\n': + case '(': + case ')': + case ':': + case ';': + final = TRUE; + break; + } + + if (final) + break; + + end ++; + if (end >= length) + break; + } + + if (end == begin) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + addr_spec = malloc(end - cur_token + 1); + if (addr_spec == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + count = end - cur_token; + src = message + cur_token; + dest = addr_spec; + for(i = 0 ; i < count ; i ++) { + if ((* src != ' ') && (* src != '\t')) { + * dest = * src; + dest ++; + } + src ++; + } + * dest = '\0'; + +#if 0 + strncpy(addr_spec, message + cur_token, end - cur_token); + addr_spec[end - cur_token] = '\0'; +#endif + + cur_token = end; + +#if 0 + r = mailimf_local_part_parse(message, length, &cur_token, &local_part); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_at_sign_parse(message, length, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + r = mailimf_domain_parse(message, length, &cur_token, &domain); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_local_part; + } + break; + + case MAILIMF_ERROR_PARSE: + domain = NULL; + break; + + default: + res = r; + goto free_local_part; + } + + if (domain) { + addr_spec = malloc(strlen(local_part) + strlen(domain) + 2); + if (addr_spec == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_domain; + } + + strcpy(addr_spec, local_part); + strcat(addr_spec, "@"); + strcat(addr_spec, domain); + + mailimf_domain_free(domain); + mailimf_local_part_free(local_part); + } + else { + addr_spec = local_part; + } +#endif + + * result = addr_spec; + * index = cur_token; + + return MAILIMF_NO_ERROR; + +#if 0 + free_domain: + mailimf_domain_free(domain); + free_local_part: + mailimf_local_part_free(local_part); +#endif + err: + return res; +} + +/* +local-part = dot-atom / quoted-string / obs-local-part +*/ + +#if 0 +static int mailimf_local_part_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + int r; + + r = mailimf_dot_atom_parse(message, length, index, result); + switch (r) { + case MAILIMF_NO_ERROR: + return r; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_quoted_string_parse(message, length, index, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +domain = dot-atom / domain-literal / obs-domain +*/ + +#if 0 +static int mailimf_domain_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + int r; + + r = mailimf_dot_atom_parse(message, length, index, result); + switch (r) { + case MAILIMF_NO_ERROR: + return r; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_domain_literal_parse(message, length, index, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +[FWS] dcontent +*/ + +#if 0 +static int +mailimf_domain_literal_fws_dcontent_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_dcontent_parse(message, length, &cur_token, &ch); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +domain-literal = [CFWS] "[" *([FWS] dcontent) [FWS] "]" [CFWS] +*/ + +#if 0 +static int mailimf_domain_literal_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + int len; + int begin; + char * domain_literal; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + begin = cur_token; + r = mailimf_obracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + while (1) { + r = mailimf_domain_literal_fws_dcontent_parse(message, length, + &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else + return r; + } + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_cbracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + len = cur_token - begin; + + domain_literal = malloc(len + 1); + if (domain_literal == NULL) + return MAILIMF_ERROR_MEMORY; + strncpy(domain_literal, message + begin, len); + domain_literal[len] = '\0'; + + * result = domain_literal; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +dcontent = dtext / quoted-pair +*/ + +#if 0 +static int mailimf_dcontent_parse(const char * message, size_t length, + size_t * index, char * result) +{ + size_t cur_token; + char ch; + int r; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_dtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * index = cur_token; + * result = ch; + + return MAILIMF_NO_ERROR; +} +#endif + + +/* +dtext = NO-WS-CTL / ; Non white space controls + + %d33-90 / ; The rest of the US-ASCII + %d94-126 ; characters not including "[", + ; "]", or "\" +*/ + +static inline int is_dtext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (is_no_ws_ctl(ch)) + return TRUE; + + if (uch < 33) + return FALSE; + + if ((uch >= 91) && (uch <= 93)) + return FALSE; + + if (uch == 127) + return FALSE; + + return TRUE; +} + +/* +message = (fields / obs-fields) + [CRLF body] +*/ + +int mailimf_message_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message ** result) +{ + struct mailimf_fields * fields; + struct mailimf_body * body; + struct mailimf_message * msg; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_fields_parse(message, length, &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_crlf_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_body_parse(message, length, &cur_token, &body); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_fields; + } + + msg = mailimf_message_new(fields, body); + if (msg == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_body; + } + + * index = cur_token; + * result = msg; + + return MAILIMF_NO_ERROR; + + free_body: + mailimf_body_free(body); + free_fields: + mailimf_fields_free(fields); + err: + return res; +} + +/* +body = *(*998text CRLF) *998text +*/ + +int mailimf_body_parse(const char * message, size_t length, + size_t * index, + struct mailimf_body ** result) +{ + size_t cur_token; + struct mailimf_body * body; + + cur_token = * index; + + body = mailimf_body_new(message + cur_token, length - cur_token); + if (body == NULL) + return MAILIMF_ERROR_MEMORY; + + cur_token = length; + + * result = body; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +CHANGE TO THE RFC 2822 + +original : + +fields = *(trace + *(resent-date / + resent-from / + resent-sender / + resent-to / + resent-cc / + resent-bcc / + resent-msg-id)) + *(orig-date / + from / + sender / + reply-to / + to / + cc / + bcc / + message-id / + in-reply-to / + references / + subject / + comments / + keywords / + optional-field) + +INTO THE FOLLOWING : +*/ + +/* +resent-fields-list = *(resent-date / + resent-from / + resent-sender / + resent-to / + resent-cc / + resent-bcc / + resent-msg-id)) +*/ + +#if 0 +enum { + RESENT_HEADER_START, +}; + +static int guess_resent_header_type(char * message, + size_t length, size_t index) +{ + int r; + + r = mailimf_token_case_insensitive_parse(message, + length, &index, "Resent-"); + if (r != MAILIMF_NO_ERROR) + return MAILIMF_RESENT_FIELD_NONE; + + if (index >= length) + return MAILIMF_RESENT_FIELD_NONE; + + switch(toupper(message[index])) { + case 'D': + return MAILIMF_RESENT_FIELD_DATE; + case 'F': + return MAILIMF_RESENT_FIELD_FROM; + case 'S': + return MAILIMF_RESENT_FIELD_SENDER; + case 'T': + return MAILIMF_RESENT_FIELD_TO; + case 'C': + return MAILIMF_RESENT_FIELD_CC; + case 'B': + return MAILIMF_RESENT_FIELD_BCC; + case 'M': + return MAILIMF_RESENT_FIELD_MSG_ID; + default: + return MAILIMF_RESENT_FIELD_NONE; + } +} +#endif + +#if 0 +static int +mailimf_resent_field_parse(const char * message, size_t length, + size_t * index, + struct mailimf_resent_field ** result) +{ + struct mailimf_orig_date * resent_date; + struct mailimf_from * resent_from; + struct mailimf_sender * resent_sender; + struct mailimf_to* resent_to; + struct mailimf_cc * resent_cc; + struct mailimf_bcc * resent_bcc; + struct mailimf_message_id * resent_msg_id; + size_t cur_token; + int type; + struct mailimf_resent_field * resent_field; + int r; + int res; + + cur_token = * index; + + resent_date = NULL; + resent_from = NULL; + resent_sender = NULL; + resent_to = NULL; + resent_cc = NULL; + resent_bcc = NULL; + resent_msg_id = NULL; + + type = guess_resent_header_type(message, length, cur_token); + + switch(type) { + case MAILIMF_RESENT_FIELD_DATE: + r = mailimf_resent_date_parse(message, length, &cur_token, + &resent_date); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_FROM: + r = mailimf_resent_from_parse(message, length, &cur_token, + &resent_from); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_SENDER: + r = mailimf_resent_sender_parse(message, length, &cur_token, + &resent_sender); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_TO: + r = mailimf_resent_to_parse(message, length, &cur_token, + &resent_to); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_CC: + r= mailimf_resent_cc_parse(message, length, &cur_token, + &resent_cc); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_BCC: + r = mailimf_resent_bcc_parse(message, length, &cur_token, + &resent_bcc); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + case MAILIMF_RESENT_FIELD_MSG_ID: + r = mailimf_resent_msg_id_parse(message, length, &cur_token, + &resent_msg_id); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + break; + default: + res = MAILIMF_ERROR_PARSE; + goto err; + } + + resent_field = mailimf_resent_field_new(type, resent_date, + resent_from, resent_sender, + resent_to, resent_cc, + resent_bcc, resent_msg_id); + if (resent_field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_resent; + } + + * result = resent_field; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_resent: + if (resent_msg_id != NULL) + mailimf_message_id_free(resent_msg_id); + if (resent_bcc != NULL) + mailimf_bcc_free(resent_bcc); + if (resent_cc != NULL) + mailimf_cc_free(resent_cc); + if (resent_to != NULL) + mailimf_to_free(resent_to); + if (resent_sender != NULL) + mailimf_sender_free(resent_sender); + if (resent_from != NULL) + mailimf_from_free(resent_from); + if (resent_date != NULL) + mailimf_orig_date_free(resent_date); + err: + return res; +} +#endif + +#if 0 +static int +mailimf_resent_fields_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_resent_fields_list ** result) +{ + clist * list; + size_t cur_token; + struct mailimf_resent_fields_list * resent_fields_list; + int r; + int res; + + cur_token = * index; + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, &list, + (mailimf_struct_parser *) + mailimf_resent_field_parse, + (mailimf_struct_destructor *) + mailimf_resent_field_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + resent_fields_list = mailimf_resent_fields_list_new(list); + if (resent_fields_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = resent_fields_list; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_resent_field_free, NULL); + clist_free(list); + err: + return res; +} +#endif + +/* + ([trace] + [resent-fields-list]) +*/ + +#if 0 +static int +mailimf_trace_resent_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_trace_resent_fields ** result) +{ + size_t cur_token; + struct mailimf_return * return_path; + struct mailimf_resent_fields_list * resent_fields; + struct mailimf_trace_resent_fields * trace_resent_fields; + int res; + int r; + + cur_token = * index; + + return_path = NULL; + resent_fields = NULL; + + r = mailimf_return_parse(message, length, &cur_token, + &return_path); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_resent_fields_list_parse(message, length, &cur_token, + &resent_fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + if ((return_path == NULL) && (resent_fields == NULL)) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + trace_resent_fields = mailimf_trace_resent_fields_new(return_path, + resent_fields); + if (trace_resent_fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_resent_fields; + } + + * result = trace_resent_fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_resent_fields: + if (resent_fields != NULL) + mailimf_resent_fields_list_free(resent_fields); + if (return_path != NULL) + mailimf_return_free(return_path); + err: + return res; +} +#endif + +/* +delivering-info = *([trace] + [resent-fields-list]) +*/ + +#if 0 +static int +mailimf_delivering_info_parse(const char * message, size_t length, + size_t * index, + struct mailimf_delivering_info ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_delivering_info * delivering_info; + int r; + int res; + + cur_token = * index; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_trace_resent_fields_parse, + (mailimf_struct_destructor *) + mailimf_trace_resent_fields_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + delivering_info = mailimf_delivering_info_new(list); + if (delivering_info == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = delivering_info; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_trace_resent_fields_free, NULL); + clist_free(list); + err: + return res; +} +#endif + +/* +field = delivering-info / + orig-date / + from / + sender / + reply-to / + to / + cc / + bcc / + message-id / + in-reply-to / + references / + subject / + comments / + keywords / + optional-field +*/ + +enum { + HEADER_START, + HEADER_C, + HEADER_R, + HEADER_RE, + HEADER_S, + HEADER_RES +}; + +static int guess_header_type(const char * message, size_t length, size_t index) +{ + int state; + int r; + + state = HEADER_START; + + while (1) { + + if (index >= length) + return MAILIMF_FIELD_NONE; + + switch(state) { + case HEADER_START: + switch((char) toupper((unsigned char) message[index])) { + case 'B': + return MAILIMF_FIELD_BCC; + case 'C': + state = HEADER_C; + break; + case 'D': + return MAILIMF_FIELD_ORIG_DATE; + case 'F': + return MAILIMF_FIELD_FROM; + case 'I': + return MAILIMF_FIELD_IN_REPLY_TO; + case 'K': + return MAILIMF_FIELD_KEYWORDS; + case 'M': + return MAILIMF_FIELD_MESSAGE_ID; + case 'R': + state = HEADER_R; + break; + case 'T': + return MAILIMF_FIELD_TO; + break; + case 'S': + state = HEADER_S; + break; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_C: + switch((char) toupper((unsigned char) message[index])) { + case 'O': + return MAILIMF_FIELD_COMMENTS; + case 'C': + return MAILIMF_FIELD_CC; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_R: + switch((char) toupper((unsigned char) message[index])) { + case 'E': + state = HEADER_RE; + break; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_RE: + switch((char) toupper((unsigned char) message[index])) { + case 'F': + return MAILIMF_FIELD_REFERENCES; + case 'P': + return MAILIMF_FIELD_REPLY_TO; + case 'S': + state = HEADER_RES; + break; + case 'T': + return MAILIMF_FIELD_RETURN_PATH; + default: + return MAILIMF_FIELD_NONE; + } + break; + case HEADER_S: + switch((char) toupper((unsigned char) message[index])) { + case 'E': + return MAILIMF_FIELD_SENDER; + case 'U': + return MAILIMF_FIELD_SUBJECT; + default: + return MAILIMF_FIELD_NONE; + } + break; + + case HEADER_RES: + r = mailimf_token_case_insensitive_parse(message, + length, &index, "ent-"); + if (r != MAILIMF_NO_ERROR) + return MAILIMF_FIELD_NONE; + + if (index >= length) + return MAILIMF_FIELD_NONE; + + switch((char) toupper((unsigned char) message[index])) { + case 'D': + return MAILIMF_FIELD_RESENT_DATE; + case 'F': + return MAILIMF_FIELD_RESENT_FROM; + case 'S': + return MAILIMF_FIELD_RESENT_SENDER; + case 'T': + return MAILIMF_FIELD_RESENT_TO; + case 'C': + return MAILIMF_FIELD_RESENT_CC; + case 'B': + return MAILIMF_FIELD_RESENT_BCC; + case 'M': + return MAILIMF_FIELD_RESENT_MSG_ID; + default: + return MAILIMF_FIELD_NONE; + } + break; + } + index ++; + } +} + +static int mailimf_field_parse(const char * message, size_t length, + size_t * index, + struct mailimf_field ** result) +{ + size_t cur_token; + int type; + struct mailimf_return * return_path; + struct mailimf_orig_date * resent_date; + struct mailimf_from * resent_from; + struct mailimf_sender * resent_sender; + struct mailimf_to* resent_to; + struct mailimf_cc * resent_cc; + struct mailimf_bcc * resent_bcc; + struct mailimf_message_id * resent_msg_id; + struct mailimf_orig_date * orig_date; + struct mailimf_from * from; + struct mailimf_sender * sender; + struct mailimf_reply_to * reply_to; + struct mailimf_to * to; + struct mailimf_cc * cc; + struct mailimf_bcc * bcc; + struct mailimf_message_id * message_id; + struct mailimf_in_reply_to * in_reply_to; + struct mailimf_references * references; + struct mailimf_subject * subject; + struct mailimf_comments * comments; + struct mailimf_keywords * keywords; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + int guessed_type; + int r; + int res; + + cur_token = * index; + + return_path = NULL; + resent_date = NULL; + resent_from = NULL; + resent_sender = NULL; + resent_to = NULL; + resent_cc = NULL; + resent_bcc = NULL; + resent_msg_id = NULL; + orig_date = NULL; + from = NULL; + sender = NULL; + reply_to = NULL; + to = NULL; + cc = NULL; + bcc = NULL; + message_id = NULL; + in_reply_to = NULL; + references = NULL; + subject = NULL; + comments = NULL; + keywords = NULL; + optional_field = NULL; + + guessed_type = guess_header_type(message, length, cur_token); + type = MAILIMF_FIELD_NONE; + + switch (guessed_type) { + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_orig_date_parse(message, length, &cur_token, + &orig_date); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_FIELD_ORIG_DATE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_FROM: + r = mailimf_from_parse(message, length, &cur_token, + &from); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_sender_parse(message, length, &cur_token, + &sender); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_reply_to_parse(message, length, &cur_token, + &reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_TO: + r = mailimf_to_parse(message, length, &cur_token, + &to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_CC: + r = mailimf_cc_parse(message, length, &cur_token, + &cc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_BCC: + r = mailimf_bcc_parse(message, length, &cur_token, + &bcc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_message_id_parse(message, length, &cur_token, + &message_id); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_in_reply_to_parse(message, length, &cur_token, + &in_reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_references_parse(message, length, &cur_token, + &references); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_subject_parse(message, length, &cur_token, + &subject); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_COMMENTS: + r = mailimf_comments_parse(message, length, &cur_token, + &comments); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_KEYWORDS: + r = mailimf_keywords_parse(message, length, &cur_token, + &keywords); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RETURN_PATH: + r = mailimf_return_parse(message, length, &cur_token, + &return_path); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_DATE: + r = mailimf_resent_date_parse(message, length, &cur_token, + &resent_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_FROM: + r = mailimf_resent_from_parse(message, length, &cur_token, + &resent_from); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_SENDER: + r = mailimf_resent_sender_parse(message, length, &cur_token, + &resent_sender); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_TO: + r = mailimf_resent_to_parse(message, length, &cur_token, + &resent_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_CC: + r= mailimf_resent_cc_parse(message, length, &cur_token, + &resent_cc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_BCC: + r = mailimf_resent_bcc_parse(message, length, &cur_token, + &resent_bcc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + r = mailimf_resent_msg_id_parse(message, length, &cur_token, + &resent_msg_id); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + } + + if (type == MAILIMF_FIELD_NONE) { + r = mailimf_optional_field_parse(message, length, &cur_token, + &optional_field); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + type = MAILIMF_FIELD_OPTIONAL_FIELD; + } + + field = mailimf_field_new(type, return_path, resent_date, + resent_from, resent_sender, resent_to, resent_cc, resent_bcc, + resent_msg_id, orig_date, from, sender, reply_to, to, + cc, bcc, message_id, in_reply_to, references, + subject, comments, keywords, optional_field); + if (field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_field; + } + + * result = field; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_field: + if (return_path != NULL) + mailimf_return_free(return_path); + if (resent_date != NULL) + mailimf_orig_date_free(resent_date); + if (resent_from != NULL) + mailimf_from_free(resent_from); + if (resent_sender != NULL) + mailimf_sender_free(resent_sender); + if (resent_to != NULL) + mailimf_to_free(resent_to); + if (resent_cc != NULL) + mailimf_cc_free(resent_cc); + if (resent_bcc != NULL) + mailimf_bcc_free(resent_bcc); + if (resent_msg_id != NULL) + mailimf_message_id_free(resent_msg_id); + if (orig_date != NULL) + mailimf_orig_date_free(orig_date); + if (from != NULL) + mailimf_from_free(from); + if (sender != NULL) + mailimf_sender_free(sender); + if (reply_to != NULL) + mailimf_reply_to_free(reply_to); + if (to != NULL) + mailimf_to_free(to); + if (cc != NULL) + mailimf_cc_free(cc); + if (bcc != NULL) + mailimf_bcc_free(bcc); + if (message_id != NULL) + mailimf_message_id_free(message_id); + if (in_reply_to != NULL) + mailimf_in_reply_to_free(in_reply_to); + if (references != NULL) + mailimf_references_free(references); + if (subject != NULL) + mailimf_subject_free(subject); + if (comments != NULL) + mailimf_comments_free(comments); + if (keywords != NULL) + mailimf_keywords_free(keywords); + if (optional_field != NULL) + mailimf_optional_field_free(optional_field); + err: + return res; +} + + +/* +fields = *(delivering-info / + orig-date / + from / + sender / + reply-to / + to / + cc / + bcc / + message-id / + in-reply-to / + references / + subject / + comments / + keywords / + optional-field) +*/ + +#if 0 +int +mailimf_unparsed_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_unparsed_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_unparsed_fields * fields; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_optional_field_parse, + (mailimf_struct_destructor *) + mailimf_optional_field_free); + /* + if ((r = MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + */ + + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_unparsed_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_optional_field_free, NULL); + clist_free(list); + } + err: + return res; +} +#endif + +int mailimf_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_field_parse, + (mailimf_struct_destructor *) + mailimf_field_free); + /* + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + */ + + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} + +/* +orig-date = "Date:" date-time CRLF +*/ + + +static int +mailimf_orig_date_parse(const char * message, size_t length, + size_t * index, struct mailimf_orig_date ** result) +{ + struct mailimf_date_time * date_time; + struct mailimf_orig_date * orig_date; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Date:"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_date_time_parse(message, length, &cur_token, &date_time); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_ignore_unstructured_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + orig_date = mailimf_orig_date_new(date_time); + if (orig_date == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_date_time; + } + + * result = orig_date; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_date_time: + mailimf_date_time_free(date_time); + err: + return res; +} + +/* +from = "From:" mailbox-list CRLF +*/ + +static int +mailimf_from_parse(const char * message, size_t length, + size_t * index, struct mailimf_from ** result) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "From"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb_list; + } + + from = mailimf_from_new(mb_list); + if (from == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb_list; + } + + * result = from; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb_list: + mailimf_mailbox_list_free(mb_list); + err: + return res; +} + +/* +sender = "Sender:" mailbox CRLF +*/ + +static int +mailimf_sender_parse(const char * message, size_t length, + size_t * index, struct mailimf_sender ** result) +{ + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Sender"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_parse(message, length, &cur_token, &mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb; + } + + sender = mailimf_sender_new(mb); + if (sender == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb; + } + + * result = sender; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb: + mailimf_mailbox_free(mb); + err: + return res; +} + +/* +reply-to = "Reply-To:" address-list CRLF +*/ + + +static int +mailimf_reply_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_reply_to ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_reply_to * reply_to; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Reply-To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + reply_to = mailimf_reply_to_new(addr_list); + if (reply_to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = reply_to; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +to = "To:" address-list CRLF +*/ + +static int +mailimf_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_to ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + to = mailimf_to_new(addr_list); + if (to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = to; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +cc = "Cc:" address-list CRLF +*/ + + +static int +mailimf_cc_parse(const char * message, size_t length, + size_t * index, struct mailimf_cc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Cc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + cc = mailimf_cc_new(addr_list); + if (cc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = cc; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +bcc = "Bcc:" (address-list / [CFWS]) CRLF +*/ + + +static int +mailimf_bcc_parse(const char * message, size_t length, + size_t * index, struct mailimf_bcc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + size_t cur_token; + int r; + int res; + + cur_token = * index; + addr_list = NULL; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Bcc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + case MAILIMF_ERROR_PARSE: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + break; + default: + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + bcc = mailimf_bcc_new(addr_list); + if (bcc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + * result = bcc; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + err: + if (addr_list != NULL) + mailimf_address_list_free(addr_list); + return res; +} + +/* +message-id = "Message-ID:" msg-id CRLF +*/ + +static int mailimf_message_id_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message_id ** result) +{ + char * value; + size_t cur_token; + struct mailimf_message_id * message_id; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Message-ID"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + message_id = mailimf_message_id_new(value); + if (message_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = message_id; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_msg_id_free(value); + err: + return res; +} + +/* +in-reply-to = "In-Reply-To:" 1*msg-id CRLF +*/ + +int mailimf_msg_id_list_parse(const char * message, size_t length, + size_t * index, clist ** result) +{ + return mailimf_struct_multiple_parse(message, length, index, + result, + (mailimf_struct_parser *) + mailimf_unstrict_msg_id_parse, + (mailimf_struct_destructor *) + mailimf_msg_id_free); +} + +static int mailimf_in_reply_to_parse(const char * message, size_t length, + size_t * index, + struct mailimf_in_reply_to ** result) +{ + struct mailimf_in_reply_to * in_reply_to; + size_t cur_token; + clist * msg_id_list; + int res; + int r; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "In-Reply-To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_list; + } + + in_reply_to = mailimf_in_reply_to_new(msg_id_list); + if (in_reply_to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = in_reply_to; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL); + clist_free(msg_id_list); + err: + return res; +} + +/* +references = "References:" 1*msg-id CRLF +*/ + +int mailimf_references_parse(const char * message, size_t length, + size_t * index, + struct mailimf_references ** result) +{ + struct mailimf_references * references; + size_t cur_token; + clist * msg_id_list; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "References"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_list_parse(message, length, &cur_token, &msg_id_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_list; + } + + references = mailimf_references_new(msg_id_list); + if (references == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = references; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL); + clist_free(msg_id_list); + err: + return res; +} + +/* +msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS] +*/ + +int mailimf_msg_id_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + size_t cur_token; +#if 0 + char * id_left; + char * id_right; +#endif + char * msg_id; + int r; + int res; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_lower_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_addr_spec_parse(message, length, &cur_token, &msg_id); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + free(msg_id); + res = r; + goto err; + } + +#if 0 + r = mailimf_id_left_parse(message, length, &cur_token, &id_left); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_at_sign_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_id_left; + } + + r = mailimf_id_right_parse(message, length, &cur_token, &id_right); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_id_left; + } + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_id_right; + } + + msg_id = malloc(strlen(id_left) + strlen(id_right) + 2); + if (msg_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_id_right; + } + strcpy(msg_id, id_left); + strcat(msg_id, "@"); + strcat(msg_id, id_right); + + mailimf_id_left_free(id_left); + mailimf_id_right_free(id_right); +#endif + + * result = msg_id; + * index = cur_token; + + return MAILIMF_NO_ERROR; + +#if 0 + free_id_right: + mailimf_id_right_free(id_right); + free_id_left: + mailimf_id_left_free(id_left); +#endif + /* + free: + mailimf_atom_free(msg_id); + */ + err: + return res; +} + +static int mailimf_parse_unwanted_msg_id(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + int r; + char * word; + int token_parsed; + + cur_token = * index; + + token_parsed = TRUE; + while (token_parsed) { + token_parsed = FALSE; + r = mailimf_word_parse(message, length, &cur_token, &word); + if (r == MAILIMF_NO_ERROR) { + mailimf_word_free(word); + token_parsed = TRUE; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_semi_colon_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_comma_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_plus_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_colon_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_point_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + r = mailimf_at_sign_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) + token_parsed = TRUE; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else + return r; + } + + return MAILIMF_NO_ERROR; +} + +static int mailimf_unstrict_msg_id_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + char * msgid; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_parse_unwanted_msg_id(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_parse(message, length, &cur_token, &msgid); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_parse_unwanted_msg_id(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + free(msgid); + return r; + } + + * result = msgid; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +id-left = dot-atom-text / no-fold-quote / obs-id-left +*/ + +#if 0 +static int mailimf_id_left_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + int r; + + r = mailimf_dot_atom_text_parse(message, length, index, result); + switch (r) { + case MAILIMF_NO_ERROR: + return MAILIMF_NO_ERROR; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_no_fold_quote_parse(message, length, index, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +id-right = dot-atom-text / no-fold-literal / obs-id-right +*/ + +#if 0 +static int mailimf_id_right_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + int r; + + r = mailimf_dot_atom_text_parse(message, length, index, result); + switch (r) { + case MAILIMF_NO_ERROR: + return MAILIMF_NO_ERROR; + case MAILIMF_ERROR_PARSE: + break; + default: + return r; + } + + r = mailimf_no_fold_literal_parse(message, length, index, result); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +/* +no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE +*/ + +#if 0 +static int mailimf_no_fold_quote_char_parse(const char * message, size_t length, + size_t * index, char * result) +{ + char ch; + size_t cur_token; + int r; + + cur_token = * index; + +#if 0 + r = mailimf_qtext_parse(message, length, &cur_token, &ch); +#endif + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_qtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * index = cur_token; + * result = ch; + + return MAILIMF_NO_ERROR; +} +#endif + +#if 0 +static int mailimf_no_fold_quote_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + size_t begin; + char ch; + char * no_fold_quote; + int r; + int res; + + begin = cur_token; + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + while (1) { + r = mailimf_no_fold_quote_char_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto err; + } + } + + r = mailimf_dquote_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + /* no_fold_quote = strndup(message + begin, cur_token - begin); */ + no_fold_quote = malloc(cur_token - begin + 1); + if (no_fold_quote == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + strncpy(no_fold_quote, message + begin, cur_token - begin); + no_fold_quote[cur_token - begin] = '\0'; + + * result = no_fold_quote; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + err: + return res; +} +#endif + +/* +no-fold-literal = "[" *(dtext / quoted-pair) "]" +*/ + +#if 0 +static inline int +mailimf_no_fold_literal_char_parse(const char * message, size_t length, + size_t * index, char * result) +{ + char ch; + size_t cur_token; + int r; + + cur_token = * index; + +#if 0 + r = mailimf_dtext_parse(message, length, &cur_token, &ch); +#endif + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + if (is_dtext(message[cur_token])) { + ch = message[cur_token]; + cur_token ++; + } + else { + r = mailimf_quoted_pair_parse(message, length, &cur_token, &ch); + + if (r != MAILIMF_NO_ERROR) + return r; + } + + * index = cur_token; + * result = ch; + + return MAILIMF_NO_ERROR; +} +#endif + +#if 0 +static int mailimf_no_fold_literal_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + size_t begin; + char ch; + char * no_fold_literal; + int r; + int res; + + begin = cur_token; + r = mailimf_obracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + while (1) { + r = mailimf_no_fold_literal_char_parse(message, length, + &cur_token, &ch); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto err; + } + } + + r = mailimf_cbracket_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + /* + no_fold_literal = strndup(message + begin, cur_token - begin); + */ + no_fold_literal = malloc(cur_token - begin + 1); + if (no_fold_literal == NULL) { + res = MAILIMF_NO_ERROR; + goto err; + } + strncpy(no_fold_literal, message + begin, cur_token - begin); + no_fold_literal[cur_token - begin] = '\0'; + + * result = no_fold_literal; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + err: + return res; +} +#endif + +/* +subject = "Subject:" unstructured CRLF +*/ + +static int mailimf_subject_parse(const char * message, size_t length, + size_t * index, + struct mailimf_subject ** result) +{ + struct mailimf_subject * subject; + char * value; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Subject"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstructured_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + subject = mailimf_subject_new(value); + if (subject == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = subject; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_unstructured_free(value); + err: + return res; +} + +/* +comments = "Comments:" unstructured CRLF +*/ + +static int mailimf_comments_parse(const char * message, size_t length, + size_t * index, + struct mailimf_comments ** result) +{ + struct mailimf_comments * comments; + char * value; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Comments"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstructured_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + comments = mailimf_comments_new(value); + if (comments == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = comments; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_unstructured_free(value); + err: + return res; +} + +/* +keywords = "Keywords:" phrase *("," phrase) CRLF +*/ + +static int mailimf_keywords_parse(const char * message, size_t length, + size_t * index, + struct mailimf_keywords ** result) +{ + struct mailimf_keywords * keywords; + clist * list; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Keywords"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_struct_list_parse(message, length, &cur_token, + &list, ',', + (mailimf_struct_parser *) + mailimf_phrase_parse, + (mailimf_struct_destructor *) + mailimf_phrase_free); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_list; + } + + keywords = mailimf_keywords_new(list); + if (keywords == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = keywords; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailimf_phrase_free, NULL); + clist_free(list); + err: + return res; +} + +/* +resent-date = "Resent-Date:" date-time CRLF +*/ + +static int +mailimf_resent_date_parse(const char * message, size_t length, + size_t * index, struct mailimf_orig_date ** result) +{ + struct mailimf_orig_date * orig_date; + struct mailimf_date_time * date_time; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Date"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_date_time_parse(message, length, &cur_token, &date_time); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + orig_date = mailimf_orig_date_new(date_time); + if (orig_date == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_date_time; + } + + * result = orig_date; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_date_time: + mailimf_date_time_free(date_time); + err: + return res; +} + +/* +resent-from = "Resent-From:" mailbox-list CRLF +*/ + +static int +mailimf_resent_from_parse(const char * message, size_t length, + size_t * index, struct mailimf_from ** result) +{ + struct mailimf_mailbox_list * mb_list; + struct mailimf_from * from; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-From"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_list_parse(message, length, &cur_token, &mb_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb_list; + } + + from = mailimf_from_new(mb_list); + if (from == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb_list; + } + + * result = from; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb_list: + mailimf_mailbox_list_free(mb_list); + err: + return res; +} + +/* +resent-sender = "Resent-Sender:" mailbox CRLF +*/ + +static int +mailimf_resent_sender_parse(const char * message, size_t length, + size_t * index, struct mailimf_sender ** result) +{ + struct mailimf_mailbox * mb; + struct mailimf_sender * sender; + size_t cur_token; + int r; + int res; + + cur_token = length; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Sender"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_parse(message, length, &cur_token, &mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_mb; + } + + sender = mailimf_sender_new(mb); + if (sender == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb; + } + + * result = sender; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_mb: + mailimf_mailbox_free(mb); + err: + return res; +} + +/* +resent-to = "Resent-To:" address-list CRLF +*/ + +static int +mailimf_resent_to_parse(const char * message, size_t length, + size_t * index, struct mailimf_to ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_to * to; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-To"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + to = mailimf_to_new(addr_list); + if (to == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = to; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +resent-cc = "Resent-Cc:" address-list CRLF +*/ + +static int +mailimf_resent_cc_parse(const char * message, size_t length, + size_t * index, struct mailimf_cc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_cc * cc; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Cc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + cc = mailimf_cc_new(addr_list); + if (cc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = cc; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +resent-bcc = "Resent-Bcc:" (address-list / [CFWS]) CRLF +*/ + +static int +mailimf_resent_bcc_parse(const char * message, size_t length, + size_t * index, struct mailimf_bcc ** result) +{ + struct mailimf_address_list * addr_list; + struct mailimf_bcc * bcc; + size_t cur_token; + int r; + int res; + + cur_token = * index; + bcc = NULL; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Bcc"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_parse(message, length, &cur_token, &addr_list); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr_list; + } + + bcc = mailimf_bcc_new(addr_list); + if (bcc == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_list; + } + + * result = bcc; + * index = cur_token; + + return TRUE; + + free_addr_list: + mailimf_address_list_free(addr_list); + err: + return res; +} + +/* +resent-msg-id = "Resent-Message-ID:" msg-id CRLF +*/ + +static int +mailimf_resent_msg_id_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message_id ** result) +{ + char * value; + size_t cur_token; + struct mailimf_message_id * message_id; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Resent-Message-ID"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_msg_id_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + message_id = mailimf_message_id_new(value); + if (message_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = message_id; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_msg_id_free(value); + err: + return res; +} + +/* +trace = [return] + 1*received +*/ + +#if 0 +static int mailimf_trace_parse(const char * message, size_t length, + size_t * index, + struct mailimf_trace ** result) +{ + size_t cur_token; + struct mailimf_return * return_path; + clist * received_list; + struct mailimf_trace * trace; + int r; + int res; + + cur_token = * index; + return_path = NULL; + received_list = NULL; + + r = mailimf_return_parse(message, length, &cur_token, &return_path); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &received_list, + (mailimf_struct_parser *) + mailimf_received_parse, + (mailimf_struct_destructor *) + mailimf_received_free); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + if ((received_list == NULL) && (return_path == NULL)) { + res = MAILIMF_ERROR_PARSE; + goto free_return; + } + + trace = mailimf_trace_new(return_path, received_list); + if (trace == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = trace; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(received_list, (clist_func) mailimf_received_free, NULL); + clist_free(received_list); + free_return: + if (return_path != NULL) + mailimf_return_free(return_path); + err: + return res; +} +#endif + +/* +return = "Return-Path:" path CRLF +*/ + +static int mailimf_return_parse(const char * message, size_t length, + size_t * index, + struct mailimf_return ** result) +{ + struct mailimf_path * path; + struct mailimf_return * return_path; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Return-Path"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + path = NULL; + r = mailimf_path_parse(message, length, &cur_token, &path); + if ( r!= MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_path; + } + + return_path = mailimf_return_new(path); + if (return_path == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_path; + } + + * result = return_path; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_path: + mailimf_path_free(path); + err: + return res; +} + +/* +path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) / + obs-path +*/ + +static int mailimf_path_parse(const char * message, size_t length, + size_t * index, struct mailimf_path ** result) +{ + size_t cur_token; + char * addr_spec; + struct mailimf_path * path; + int res; + int r; + + cur_token = * index; + addr_spec = NULL; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_lower_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_addr_spec_parse(message, length, &cur_token, &addr_spec); + switch (r) { + case MAILIMF_NO_ERROR: + break; + case MAILIMF_ERROR_PARSE: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + break; + default: + return r; + } + + r = mailimf_greater_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + path = mailimf_path_new(addr_spec); + if (path == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_addr_spec; + } + + * index = cur_token; + * result = path; + + return MAILIMF_NO_ERROR; + + free_addr_spec: + if (addr_spec == NULL) + mailimf_addr_spec_free(addr_spec); + err: + return res; +} + +/* +received = "Received:" name-val-list ";" date-time CRLF +*/ + +#if 0 +static int mailimf_received_parse(const char * message, size_t length, + size_t * index, + struct mailimf_received ** result) +{ + size_t cur_token; + struct mailimf_received * received; + struct mailimf_name_val_list * name_val_list; + struct mailimf_date_time * date_time; + int r; + int res; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "Received"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_name_val_list_parse(message, length, + &cur_token, &name_val_list); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_semi_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name_val_list; + } + + r = mailimf_date_time_parse(message, length, &cur_token, &date_time); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name_val_list; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_date_time; + } + + received = mailimf_received_new(name_val_list, date_time); + if (received == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_date_time; + } + + * index = cur_token; + * result = received; + + return MAILIMF_NO_ERROR; + + free_date_time: + mailimf_date_time_free(date_time); + free_name_val_list: + mailimf_name_val_list_free(name_val_list); + err: + return res; +} +#endif + +/* +name-val-list = [CFWS] [name-val-pair *(CFWS name-val-pair)] +*/ + +#if 0 +static int +mailimf_name_val_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_name_val_list ** result) +{ + size_t cur_token; + struct mailimf_name_val_pair * pair; + struct mailimf_name_val_list * name_val_list; + clist* list; + int res; + int r; + + cur_token = * index; + list = NULL; + + r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair); + + if (r == MAILIMF_NO_ERROR){ + size_t final_token; + + list = clist_new(); + if (list == NULL) { + mailimf_name_val_pair_free(pair); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = clist_append(list, pair); + if (r < 0) { + mailimf_name_val_pair_free(pair); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + + while (1) { + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_list; + } + + r = mailimf_name_val_pair_parse(message, length, &cur_token, &pair); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) + break; + else { + res = r; + goto free_list; + } + + r = clist_append(list, pair); + if (r < 0) { + mailimf_name_val_pair_free(pair); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + final_token = cur_token; + } + cur_token = final_token; + } + + name_val_list = mailimf_name_val_list_new(list); + if (name_val_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * index = cur_token; + * result = name_val_list; + + return MAILIMF_NO_ERROR; + + free_list: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_name_val_pair_free, NULL); + clist_free(list); + } + err: + return res; +} +#endif + +/* +name-val-pair = item-name CFWS item-value +*/ + +#if 0 +static int +mailimf_name_val_pair_parse(const char * message, size_t length, + size_t * index, + struct mailimf_name_val_pair ** result) +{ + size_t cur_token; + char * item_name; + struct mailimf_item_value * item_value; + struct mailimf_name_val_pair * name_val_pair; + int r; + int res; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + r = mailimf_item_name_parse(message, length, &cur_token, &item_name); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_cfws_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_item_name; + } + + r = mailimf_item_value_parse(message, length, &cur_token, &item_value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_item_name; + } + + name_val_pair = mailimf_name_val_pair_new(item_name, item_value); + if (name_val_pair == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_item_value; + } + + * result = name_val_pair; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_item_value: + mailimf_item_value_free(item_value); + free_item_name: + mailimf_item_name_free(item_name); + err: + return res; +} +#endif + +/* +item-name = ALPHA *(["-"] (ALPHA / DIGIT)) +*/ + +#if 0 +static int mailimf_item_name_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + size_t cur_token; + size_t begin; + char * item_name; + char ch; + int digit; + int r; + int res; + + cur_token = * index; + + begin = cur_token; + + r = mailimf_alpha_parse(message, length, &cur_token, &ch); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + while (1) { + int minus_sign; + + minus_sign = mailimf_minus_parse(message, length, &cur_token); + + r = mailimf_alpha_parse(message, length, &cur_token, &ch); + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_digit_parse(message, length, &cur_token, &digit); + + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + if (r == MAILIMF_ERROR_PARSE) + break; + else if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + } + + item_name = strndup(message + begin, cur_token - begin); + if (item_name == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + * index = cur_token; + * result = item_name; + + return MAILIMF_NO_ERROR; + + err: + return res; +} +#endif + +/* +item-value = 1*angle-addr / addr-spec / + atom / domain / msg-id +*/ + +#if 0 +static int is_item_value_atext(char ch) +{ + switch (ch) { + case '\t': + case ' ': + case '\r': + case '\n': + case ';': + return FALSE; + default: + return TRUE; + } +} + +static int mailimf_item_value_atom_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * atom; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_custom_string_parse(message, length, &cur_token, + &atom, is_item_value_atext); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + * index = cur_token; + * result = atom; + + return MAILIMF_NO_ERROR; +} + +static int mailimf_item_value_parse(const char * message, size_t length, + size_t * index, + struct mailimf_item_value ** result) +{ + size_t cur_token; + clist * angle_addr_list; + char * addr_spec; + char * atom; + char * domain; + char * msg_id; + int type; + struct mailimf_item_value * item_value; + int r; + int res; + + cur_token = * index; + + angle_addr_list = NULL; + addr_spec = NULL; + atom = NULL; + domain = NULL; + msg_id = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &angle_addr_list, + (mailimf_struct_parser *) + mailimf_angle_addr_parse, + (mailimf_struct_destructor *) + mailimf_angle_addr_free); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_ANGLE_ADDR_LIST; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_addr_spec_parse(message, length, &cur_token, + &addr_spec); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_ADDR_SPEC; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_msg_id_parse(message, length, &cur_token, + &msg_id); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_MSG_ID; + } + + /* + else if (mailimf_domain_parse(message, length, &cur_token, + &domain)) + type = MAILIMF_ITEM_VALUE_DOMAIN; + */ + /* + else if (mailimf_atom_parse(message, length, &cur_token, + &atom)) + type = MAILIMF_ITEM_VALUE_ATOM; + */ + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_item_value_atom_parse(message, length, &cur_token, + &atom); + if (r == MAILIMF_NO_ERROR) + type = MAILIMF_ITEM_VALUE_ATOM; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + item_value = mailimf_item_value_new(type, angle_addr_list, addr_spec, + atom, domain, msg_id); + if (item_value == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = item_value; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (angle_addr_list != NULL) { + clist_foreach(angle_addr_list, (clist_func) mailimf_angle_addr_free, NULL); + clist_free(angle_addr_list); + } + if (addr_spec != NULL) + mailimf_addr_spec_free(addr_spec); + if (atom != NULL) + mailimf_atom_free(atom); + if (domain != NULL) + mailimf_domain_free(domain); + if (msg_id != NULL) + mailimf_msg_id_free(msg_id); + err: + return res; +} +#endif + +/* +optional-field = field-name ":" unstructured CRLF +*/ + +static int +mailimf_optional_field_parse(const char * message, size_t length, + size_t * index, + struct mailimf_optional_field ** result) +{ + char * name; + char * value; + struct mailimf_optional_field * optional_field; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailimf_field_name_parse(message, length, &cur_token, &name); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_colon_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name; + } + + r = mailimf_unstructured_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_name; + } + + r = mailimf_unstrict_crlf_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_value; + } + + optional_field = mailimf_optional_field_new(name, value); + if (optional_field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = optional_field; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailimf_unstructured_free(value); + free_name: + mailimf_field_name_free(name); + err: + return res; +} + +/* +field-name = 1*ftext +*/ + +static inline int is_ftext(char ch); + +static int mailimf_field_name_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * field_name; + size_t cur_token; + size_t end; + + cur_token = * index; + + end = cur_token; + if (end >= length) { + return MAILIMF_ERROR_PARSE; + } + + while (is_ftext(message[end])) { + end ++; + if (end >= length) + break; + } + if (end == cur_token) { + return MAILIMF_ERROR_PARSE; + } + + /* field_name = strndup(message + cur_token, end - cur_token); */ + field_name = malloc(end - cur_token + 1); + if (field_name == NULL) { + return MAILIMF_ERROR_MEMORY; + } + strncpy(field_name, message + cur_token, end - cur_token); + field_name[end - cur_token] = '\0'; + + cur_token = end; + + * index = cur_token; + * result = field_name; + + return MAILIMF_NO_ERROR; +} + +/* +ftext = %d33-57 / ; Any character except + %d59-126 ; controls, SP, and + ; ":". +*/ + +static inline int is_ftext(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (uch < 33) + return FALSE; + + if (uch == 58) + return FALSE; + + return TRUE; +} + +/* +static int mailimf_ftext_parse(const char * message, size_t length, + size_t * index, gchar * result) +{ + return mailimf_typed_text_parse(message, length, index, result, is_ftext); +} +*/ + + + + +static int mailimf_envelope_field_parse(const char * message, size_t length, + size_t * index, + struct mailimf_field ** result) +{ + size_t cur_token; + int type; + struct mailimf_orig_date * orig_date; + struct mailimf_from * from; + struct mailimf_sender * sender; + struct mailimf_reply_to * reply_to; + struct mailimf_to * to; + struct mailimf_cc * cc; + struct mailimf_bcc * bcc; + struct mailimf_message_id * message_id; + struct mailimf_in_reply_to * in_reply_to; + struct mailimf_references * references; + struct mailimf_subject * subject; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + int guessed_type; + int r; + int res; + + cur_token = * index; + + orig_date = NULL; + from = NULL; + sender = NULL; + reply_to = NULL; + to = NULL; + cc = NULL; + bcc = NULL; + message_id = NULL; + in_reply_to = NULL; + references = NULL; + subject = NULL; + optional_field = NULL; + + guessed_type = guess_header_type(message, length, cur_token); + type = MAILIMF_FIELD_NONE; + + switch (guessed_type) { + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_orig_date_parse(message, length, &cur_token, + &orig_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_FROM: + r = mailimf_from_parse(message, length, &cur_token, + &from); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_sender_parse(message, length, &cur_token, + &sender); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_reply_to_parse(message, length, &cur_token, + &reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_TO: + r = mailimf_to_parse(message, length, &cur_token, + &to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_CC: + r = mailimf_cc_parse(message, length, &cur_token, + &cc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_BCC: + r = mailimf_bcc_parse(message, length, &cur_token, + &bcc); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_message_id_parse(message, length, &cur_token, + &message_id); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_in_reply_to_parse(message, length, &cur_token, + &in_reply_to); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_references_parse(message, length, &cur_token, + &references); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_subject_parse(message, length, &cur_token, + &subject); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + } + + if (type == MAILIMF_FIELD_NONE) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + orig_date, from, sender, reply_to, to, + cc, bcc, message_id, in_reply_to, references, + subject, NULL, NULL, optional_field); + if (field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_field; + } + + * result = field; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_field: + if (orig_date != NULL) + mailimf_orig_date_free(orig_date); + if (from != NULL) + mailimf_from_free(from); + if (sender != NULL) + mailimf_sender_free(sender); + if (reply_to != NULL) + mailimf_reply_to_free(reply_to); + if (to != NULL) + mailimf_to_free(to); + if (cc != NULL) + mailimf_cc_free(cc); + if (bcc != NULL) + mailimf_bcc_free(bcc); + if (message_id != NULL) + mailimf_message_id_free(message_id); + if (in_reply_to != NULL) + mailimf_in_reply_to_free(in_reply_to); + if (references != NULL) + mailimf_references_free(references); + if (subject != NULL) + mailimf_subject_free(subject); + if (optional_field != NULL) + mailimf_optional_field_free(optional_field); + err: + return res; +} + +int mailimf_envelope_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * index; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + while (1) { + struct mailimf_field * elt; + + r = mailimf_envelope_field_parse(message, length, &cur_token, &elt); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, elt); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + else if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_ignore_field_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto free; + } + } + else { + res = r; + goto free; + } + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} + + +static int +mailimf_envelope_or_optional_field_parse(const char * message, + size_t length, + size_t * index, + struct mailimf_field ** result) +{ + int r; + size_t cur_token; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + + r = mailimf_envelope_field_parse(message, length, index, result); + if (r == MAILIMF_NO_ERROR) + return MAILIMF_NO_ERROR; + + cur_token = * index; + + r = mailimf_optional_field_parse(message, length, &cur_token, + &optional_field); + if (r != MAILIMF_NO_ERROR) + return r; + + field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, optional_field); + if (field == NULL) { + mailimf_optional_field_free(optional_field); + return MAILIMF_ERROR_MEMORY; + } + + * result = field; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + + +int +mailimf_envelope_and_optional_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_envelope_or_optional_field_parse, + (mailimf_struct_destructor *) + mailimf_field_free); + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} + + + +static int +mailimf_only_optional_field_parse(const char * message, + size_t length, + size_t * index, + struct mailimf_field ** result) +{ + int r; + size_t cur_token; + struct mailimf_optional_field * optional_field; + struct mailimf_field * field; + + cur_token = * index; + + r = mailimf_optional_field_parse(message, length, &cur_token, + &optional_field); + if (r != MAILIMF_NO_ERROR) + return r; + + field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, optional_field); + if (field == NULL) { + mailimf_optional_field_free(optional_field); + return MAILIMF_ERROR_MEMORY; + } + + * result = field; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + + +int +mailimf_optional_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result) +{ + size_t cur_token; + clist * list; + struct mailimf_fields * fields; + int r; + int res; + + cur_token = * index; + + list = NULL; + + r = mailimf_struct_multiple_parse(message, length, &cur_token, + &list, + (mailimf_struct_parser *) + mailimf_only_optional_field_parse, + (mailimf_struct_destructor *) + mailimf_field_free); + switch (r) { + case MAILIMF_NO_ERROR: + /* do nothing */ + break; + + case MAILIMF_ERROR_PARSE: + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + break; + + default: + res = r; + goto err; + } + + fields = mailimf_fields_new(list); + if (fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = fields; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (list != NULL) { + clist_foreach(list, (clist_func) mailimf_field_free, NULL); + clist_free(list); + } + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,351 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf.h,v 1.25 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILIMF_H + +#define MAILIMF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailimf_types.h> +#include <libetpan/mailimf_write_generic.h> +#include <libetpan/mailimf_write_file.h> +#include <libetpan/mailimf_write_mem.h> +#include <libetpan/mailimf_types_helper.h> + +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif + +/* + mailimf_message_parse will parse the given message + + @param message this is a string containing the message content + @param length this is the size of the given string + @param index this is a pointer to the start of the message in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_message_parse(const char * message, size_t length, + size_t * index, + struct mailimf_message ** result); + +/* + mailimf_body_parse will parse the given text part of a message + + @param message this is a string containing the message text part + @param length this is the size of the given string + @param index this is a pointer to the start of the message text part in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_body_parse(const char * message, size_t length, + size_t * index, + struct mailimf_body ** result); + +/* + mailimf_fields_parse will parse the given header fields + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + +/* + mailimf_mailbox_list_parse will parse the given mailbox list + + @param message this is a string containing the mailbox list + @param length this is the size of the given string + @param index this is a pointer to the start of the mailbox list in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int +mailimf_mailbox_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_mailbox_list ** result); + +/* + mailimf_address_list_parse will parse the given address list + + @param message this is a string containing the address list + @param length this is the size of the given string + @param index this is a pointer to the start of the address list in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int +mailimf_address_list_parse(const char * message, size_t length, + size_t * index, + struct mailimf_address_list ** result); + +/* + mailimf_address_parse will parse the given address + + @param message this is a string containing the address + @param length this is the size of the given string + @param index this is a pointer to the start of the address in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_address_parse(const char * message, size_t length, + size_t * index, + struct mailimf_address ** result); + +/* + mailimf_mailbox_parse will parse the given address + + @param message this is a string containing the mailbox + @param length this is the size of the given string + @param index this is a pointer to the start of the mailbox in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_mailbox_parse(const char * message, size_t length, + size_t * index, + struct mailimf_mailbox ** result); + +/* + mailimf_date_time_parse will parse the given RFC 2822 date + + @param message this is a string containing the date + @param length this is the size of the given string + @param index this is a pointer to the start of the date in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_date_time_parse(const char * message, size_t length, + size_t * index, + struct mailimf_date_time ** result); + +/* + mailimf_envelope_fields_parse will parse the given fields (Date, + From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To, + References and Subject) + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int mailimf_envelope_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + +/* + mailimf_ignore_field_parse will skip the given field + + @param message this is a string containing the header field + @param length this is the size of the given string + @param index this is a pointer to the start of the header field in + the given string, (* index) is modified to point at the end + of the parsed data + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +LIBETPAN_EXPORT +int mailimf_ignore_field_parse(const char * message, size_t length, + size_t * index); + +/* + mailimf_envelope_fields will parse the given fields (Date, + From, Sender, Reply-To, To, Cc, Bcc, Message-ID, In-Reply-To, + References and Subject), other fields will be added as optional + fields. + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ + +LIBETPAN_EXPORT +int +mailimf_envelope_and_optional_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + +/* + mailimf_envelope_fields will parse the given fields as optional + fields. + + @param message this is a string containing the header fields + @param length this is the size of the given string + @param index this is a pointer to the start of the header fields in + the given string, (* index) is modified to point at the end + of the parsed data + @param result the result of the parse operation is stored in + (* result) + + @return MAILIMF_NO_ERROR on success, MAILIMF_ERROR_XXX on error +*/ +LIBETPAN_EXPORT +int +mailimf_optional_fields_parse(const char * message, size_t length, + size_t * index, + struct mailimf_fields ** result); + + +/* internal use, exported for MIME */ + +int mailimf_fws_parse(const char * message, size_t length, size_t * index); + +int mailimf_cfws_parse(const char * message, size_t length, + size_t * index); + +int mailimf_char_parse(const char * message, size_t length, + size_t * index, char token); + +int mailimf_unstrict_char_parse(const char * message, size_t length, + size_t * index, char token); + +int mailimf_crlf_parse(const char * message, size_t length, size_t * index); + +int +mailimf_custom_string_parse(const char * message, size_t length, + size_t * index, char ** result, + int (* is_custom_char)(char)); + +int +mailimf_token_case_insensitive_len_parse(const char * message, size_t length, + size_t * index, char * token, + size_t token_length); + +#define mailimf_token_case_insensitive_parse(message, length, index, token) \ + mailimf_token_case_insensitive_len_parse(message, length, index, token, \ + sizeof(token) - 1) + +int mailimf_quoted_string_parse(const char * message, size_t length, + size_t * index, char ** result); + +int +mailimf_number_parse(const char * message, size_t length, + size_t * index, uint32_t * result); + +int mailimf_msg_id_parse(const char * message, size_t length, + size_t * index, + char ** result); + +int mailimf_msg_id_list_parse(const char * message, size_t length, + size_t * index, clist ** result); + +int mailimf_word_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_atom_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_fws_atom_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_fws_word_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailimf_fws_quoted_string_parse(const char * message, size_t length, + size_t * index, char ** result); + +/* exported for IMAP */ + +int mailimf_references_parse(const char * message, size_t length, + size_t * index, + struct mailimf_references ** result); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_types.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_types.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,908 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_types.c,v 1.18 2005/06/01 12:22:01 smarinier Exp $ + */ + +#include "mailimf_types.h" +#include "mmapstring.h" +#include <stdlib.h> + +void mailimf_atom_free(char * atom) +{ + free(atom); +} + +void mailimf_dot_atom_free(char * dot_atom) +{ + free(dot_atom); +} + +void mailimf_dot_atom_text_free(char * dot_atom) +{ + free(dot_atom); +} + +void mailimf_quoted_string_free(char * quoted_string) +{ + free(quoted_string); +} + +void mailimf_word_free(char * word) +{ + free(word); +} + +void mailimf_phrase_free(char * phrase) +{ + free(phrase); +} + +void mailimf_unstructured_free(char * unstructured) +{ + free(unstructured); +} + + +LIBETPAN_EXPORT +struct mailimf_date_time * +mailimf_date_time_new(int dt_day, int dt_month, int dt_year, + int dt_hour, int dt_min, int dt_sec, int dt_zone) +{ + struct mailimf_date_time * date_time; + + date_time = malloc(sizeof(* date_time)); + if (date_time == NULL) + return NULL; + + date_time->dt_day = dt_day; + date_time->dt_month = dt_month; + date_time->dt_year = dt_year; + date_time->dt_hour = dt_hour; + date_time->dt_min = dt_min; + date_time->dt_sec = dt_sec; + date_time->dt_zone = dt_zone; + + return date_time; +} + +LIBETPAN_EXPORT +void mailimf_date_time_free(struct mailimf_date_time * date_time) +{ + free(date_time); +} + + + +LIBETPAN_EXPORT +struct mailimf_address * +mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox, + struct mailimf_group * ad_group) +{ + struct mailimf_address * address; + + address = malloc(sizeof(* address)); + if (address == NULL) + return NULL; + + address->ad_type = ad_type; + switch (ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + address->ad_data.ad_mailbox = ad_mailbox; + break; + case MAILIMF_ADDRESS_GROUP: + address->ad_data.ad_group = ad_group; + break; + } + + return address; +} + +LIBETPAN_EXPORT +void mailimf_address_free(struct mailimf_address * address) +{ + switch (address->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + mailimf_mailbox_free(address->ad_data.ad_mailbox); + break; + case MAILIMF_ADDRESS_GROUP: + mailimf_group_free(address->ad_data.ad_group); + } + free(address); +} + +LIBETPAN_EXPORT +struct mailimf_mailbox * +mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec) +{ + struct mailimf_mailbox * mb; + + mb = malloc(sizeof(* mb)); + if (mb == NULL) + return NULL; + + mb->mb_display_name = mb_display_name; + mb->mb_addr_spec = mb_addr_spec; + + return mb; +} + +LIBETPAN_EXPORT +void mailimf_mailbox_free(struct mailimf_mailbox * mailbox) +{ + if (mailbox->mb_display_name != NULL) + mailimf_display_name_free(mailbox->mb_display_name); + mailimf_addr_spec_free(mailbox->mb_addr_spec); + free(mailbox); +} + +void mailimf_angle_addr_free(char * angle_addr) +{ + free(angle_addr); +} + +LIBETPAN_EXPORT +struct mailimf_group * +mailimf_group_new(char * grp_display_name, + struct mailimf_mailbox_list * grp_mb_list) +{ + struct mailimf_group * group; + + group = malloc(sizeof(* group)); + if (group == NULL) + return NULL; + + group->grp_display_name = grp_display_name; + group->grp_mb_list = grp_mb_list; + + return group; +} + +LIBETPAN_EXPORT +void mailimf_group_free(struct mailimf_group * group) +{ + if (group->grp_mb_list) + mailimf_mailbox_list_free(group->grp_mb_list); + mailimf_display_name_free(group->grp_display_name); + free(group); +} + +void mailimf_display_name_free(char * display_name) +{ + mailimf_phrase_free(display_name); +} + +LIBETPAN_EXPORT +struct mailimf_mailbox_list * +mailimf_mailbox_list_new(clist * mb_list) +{ + struct mailimf_mailbox_list * mbl; + + mbl = malloc(sizeof(* mbl)); + if (mbl == NULL) + return NULL; + + mbl->mb_list = mb_list; + + return mbl; +} + +LIBETPAN_EXPORT +void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list) +{ + clist_foreach(mb_list->mb_list, (clist_func) mailimf_mailbox_free, NULL); + clist_free(mb_list->mb_list); + free(mb_list); +} + + +LIBETPAN_EXPORT +struct mailimf_address_list * +mailimf_address_list_new(clist * ad_list) +{ + struct mailimf_address_list * addr_list; + + addr_list = malloc(sizeof(* addr_list)); + if (addr_list == NULL) + return NULL; + + addr_list->ad_list = ad_list; + + return addr_list; +} + +LIBETPAN_EXPORT +void mailimf_address_list_free(struct mailimf_address_list * addr_list) +{ + clist_foreach(addr_list->ad_list, (clist_func) mailimf_address_free, NULL); + clist_free(addr_list->ad_list); + free(addr_list); +} + + +void mailimf_addr_spec_free(char * addr_spec) +{ + free(addr_spec); +} + +void mailimf_local_part_free(char * local_part) +{ + free(local_part); +} + +void mailimf_domain_free(char * domain) +{ + free(domain); +} + +void mailimf_domain_literal_free(char * domain_literal) +{ + free(domain_literal); +} + +LIBETPAN_EXPORT +struct mailimf_message * +mailimf_message_new(struct mailimf_fields * msg_fields, + struct mailimf_body * msg_body) +{ + struct mailimf_message * message; + + message = malloc(sizeof(* message)); + if (message == NULL) + return NULL; + + message->msg_fields = msg_fields; + message->msg_body = msg_body; + + return message; +} + +LIBETPAN_EXPORT +void mailimf_message_free(struct mailimf_message * message) +{ + mailimf_body_free(message->msg_body); + mailimf_fields_free(message->msg_fields); + free(message); +} + +LIBETPAN_EXPORT +struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size) +{ + struct mailimf_body * body; + + body = malloc(sizeof(* body)); + if (body == NULL) + return NULL; + body->bd_text = bd_text; + body->bd_size = bd_size; + + return body; +} + +LIBETPAN_EXPORT +void mailimf_body_free(struct mailimf_body * body) +{ + free(body); +} + + +LIBETPAN_EXPORT +struct mailimf_field * +mailimf_field_new(int fld_type, + struct mailimf_return * fld_return_path, + struct mailimf_orig_date * fld_resent_date, + struct mailimf_from * fld_resent_from, + struct mailimf_sender * fld_resent_sender, + struct mailimf_to * fld_resent_to, + struct mailimf_cc * fld_resent_cc, + struct mailimf_bcc * fld_resent_bcc, + struct mailimf_message_id * fld_resent_msg_id, + struct mailimf_orig_date * fld_orig_date, + struct mailimf_from * fld_from, + struct mailimf_sender * fld_sender, + struct mailimf_reply_to * fld_reply_to, + struct mailimf_to * fld_to, + struct mailimf_cc * fld_cc, + struct mailimf_bcc * fld_bcc, + struct mailimf_message_id * fld_message_id, + struct mailimf_in_reply_to * fld_in_reply_to, + struct mailimf_references * fld_references, + struct mailimf_subject * fld_subject, + struct mailimf_comments * fld_comments, + struct mailimf_keywords * fld_keywords, + struct mailimf_optional_field * fld_optional_field) +{ + struct mailimf_field * field; + + field = malloc(sizeof(* field)); + if (field == NULL) + return NULL; + + field->fld_type = fld_type; + switch (fld_type) { + case MAILIMF_FIELD_RETURN_PATH: + field->fld_data.fld_return_path = fld_return_path; + break; + case MAILIMF_FIELD_RESENT_DATE: + field->fld_data.fld_resent_date = fld_resent_date; + break; + case MAILIMF_FIELD_RESENT_FROM: + field->fld_data.fld_resent_from = fld_resent_from; + break; + case MAILIMF_FIELD_RESENT_SENDER: + field->fld_data.fld_resent_sender = fld_resent_sender; + break; + case MAILIMF_FIELD_RESENT_TO: + field->fld_data.fld_resent_to = fld_resent_to; + break; + case MAILIMF_FIELD_RESENT_CC: + field->fld_data.fld_resent_cc = fld_resent_cc; + break; + case MAILIMF_FIELD_RESENT_BCC: + field->fld_data.fld_resent_bcc = fld_resent_bcc; + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + field->fld_data.fld_resent_msg_id = fld_resent_msg_id; + break; + case MAILIMF_FIELD_ORIG_DATE: + field->fld_data.fld_orig_date = fld_orig_date; + break; + case MAILIMF_FIELD_FROM: + field->fld_data.fld_from = fld_from; + break; + case MAILIMF_FIELD_SENDER: + field->fld_data.fld_sender = fld_sender; + break; + case MAILIMF_FIELD_REPLY_TO: + field->fld_data.fld_reply_to = fld_reply_to; + break; + case MAILIMF_FIELD_TO: + field->fld_data.fld_to = fld_to; + break; + case MAILIMF_FIELD_CC: + field->fld_data.fld_cc = fld_cc; + break; + case MAILIMF_FIELD_BCC: + field->fld_data.fld_bcc = fld_bcc; + break; + case MAILIMF_FIELD_MESSAGE_ID: + field->fld_data.fld_message_id = fld_message_id; + break; + case MAILIMF_FIELD_IN_REPLY_TO: + field->fld_data.fld_in_reply_to = fld_in_reply_to; + break; + case MAILIMF_FIELD_REFERENCES: + field->fld_data.fld_references = fld_references; + break; + case MAILIMF_FIELD_SUBJECT: + field->fld_data.fld_subject = fld_subject; + break; + case MAILIMF_FIELD_COMMENTS: + field->fld_data.fld_comments = fld_comments; + break; + case MAILIMF_FIELD_KEYWORDS: + field->fld_data.fld_keywords = fld_keywords; + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + field->fld_data.fld_optional_field = fld_optional_field; + break; + } + + return field; +} + +LIBETPAN_EXPORT +void mailimf_field_free(struct mailimf_field * field) +{ + switch (field->fld_type) { + case MAILIMF_FIELD_RETURN_PATH: + mailimf_return_free(field->fld_data.fld_return_path); + break; + case MAILIMF_FIELD_RESENT_DATE: + mailimf_orig_date_free(field->fld_data.fld_resent_date); + break; + case MAILIMF_FIELD_RESENT_FROM: + mailimf_from_free(field->fld_data.fld_resent_from); + break; + case MAILIMF_FIELD_RESENT_SENDER: + mailimf_sender_free(field->fld_data.fld_resent_sender); + break; + case MAILIMF_FIELD_RESENT_TO: + mailimf_to_free(field->fld_data.fld_resent_to); + break; + case MAILIMF_FIELD_RESENT_CC: + mailimf_cc_free(field->fld_data.fld_resent_cc); + break; + case MAILIMF_FIELD_RESENT_BCC: + mailimf_bcc_free(field->fld_data.fld_resent_bcc); + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + mailimf_message_id_free(field->fld_data.fld_resent_msg_id); + break; + case MAILIMF_FIELD_ORIG_DATE: + mailimf_orig_date_free(field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + mailimf_from_free(field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + mailimf_sender_free(field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + mailimf_reply_to_free(field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + mailimf_to_free(field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + mailimf_cc_free(field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + mailimf_bcc_free(field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + mailimf_message_id_free(field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + mailimf_in_reply_to_free(field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + mailimf_references_free(field->fld_data.fld_references); + break; + case MAILIMF_FIELD_SUBJECT: + mailimf_subject_free(field->fld_data.fld_subject); + break; + case MAILIMF_FIELD_COMMENTS: + mailimf_comments_free(field->fld_data.fld_comments); + break; + case MAILIMF_FIELD_KEYWORDS: + mailimf_keywords_free(field->fld_data.fld_keywords); + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + mailimf_optional_field_free(field->fld_data.fld_optional_field); + break; + } + + free(field); +} + +LIBETPAN_EXPORT +struct mailimf_fields * mailimf_fields_new(clist * fld_list) +{ + struct mailimf_fields * fields; + + fields = malloc(sizeof(* fields)); + if (fields == NULL) + return NULL; + + fields->fld_list = fld_list; + + return fields; +} + +LIBETPAN_EXPORT +void mailimf_fields_free(struct mailimf_fields * fields) +{ + if (fields->fld_list != NULL) { + clist_foreach(fields->fld_list, (clist_func) mailimf_field_free, NULL); + clist_free(fields->fld_list); + } + free(fields); +} + +LIBETPAN_EXPORT +struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time * + dt_date_time) +{ + struct mailimf_orig_date * orig_date; + + orig_date = malloc(sizeof(* orig_date)); + if (orig_date == NULL) + return NULL; + + orig_date->dt_date_time = dt_date_time; + + return orig_date; +} + +LIBETPAN_EXPORT +void mailimf_orig_date_free(struct mailimf_orig_date * orig_date) +{ + if (orig_date->dt_date_time != NULL) + mailimf_date_time_free(orig_date->dt_date_time); + free(orig_date); +} + +LIBETPAN_EXPORT +struct mailimf_from * +mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list) +{ + struct mailimf_from * from; + + from = malloc(sizeof(* from)); + if (from == NULL) + return NULL; + + from->frm_mb_list = frm_mb_list; + + return from; +} + +LIBETPAN_EXPORT +void mailimf_from_free(struct mailimf_from * from) +{ + if (from->frm_mb_list != NULL) + mailimf_mailbox_list_free(from->frm_mb_list); + free(from); +} + +LIBETPAN_EXPORT +struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb) +{ + struct mailimf_sender * sender; + + sender = malloc(sizeof(* sender)); + if (sender == NULL) + return NULL; + + sender->snd_mb = snd_mb; + + return sender; +} + +LIBETPAN_EXPORT +void mailimf_sender_free(struct mailimf_sender * sender) +{ + if (sender->snd_mb != NULL) + mailimf_mailbox_free(sender->snd_mb); + free(sender); +} + +LIBETPAN_EXPORT +struct mailimf_reply_to * +mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list) +{ + struct mailimf_reply_to * reply_to; + + reply_to = malloc(sizeof(* reply_to)); + if (reply_to == NULL) + return NULL; + + reply_to->rt_addr_list = rt_addr_list; + + return reply_to; +} + +LIBETPAN_EXPORT +void mailimf_reply_to_free(struct mailimf_reply_to * reply_to) +{ + if (reply_to->rt_addr_list != NULL) + mailimf_address_list_free(reply_to->rt_addr_list); + free(reply_to); +} + +LIBETPAN_EXPORT +struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list) +{ + struct mailimf_to * to; + + to = malloc(sizeof(* to)); + if (to == NULL) + return NULL; + + to->to_addr_list = to_addr_list; + + return to; +} + +LIBETPAN_EXPORT +void mailimf_to_free(struct mailimf_to * to) +{ + if (to->to_addr_list != NULL) + mailimf_address_list_free(to->to_addr_list); + free(to); +} + +LIBETPAN_EXPORT +struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list) +{ + struct mailimf_cc * cc; + + cc = malloc(sizeof(* cc)); + if (cc == NULL) + return NULL; + + cc->cc_addr_list = cc_addr_list; + + return cc; +} + +LIBETPAN_EXPORT +void mailimf_cc_free(struct mailimf_cc * cc) +{ + if (cc->cc_addr_list != NULL) + mailimf_address_list_free(cc->cc_addr_list); + free(cc); +} + +LIBETPAN_EXPORT +struct mailimf_bcc * +mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list) +{ + struct mailimf_bcc * bcc; + + bcc = malloc(sizeof(* bcc)); + if (bcc == NULL) + return NULL; + + bcc->bcc_addr_list = bcc_addr_list; + + return bcc; +} + +LIBETPAN_EXPORT +void mailimf_bcc_free(struct mailimf_bcc * bcc) +{ + if (bcc->bcc_addr_list != NULL) + mailimf_address_list_free(bcc->bcc_addr_list); + free(bcc); +} + +LIBETPAN_EXPORT +struct mailimf_message_id * mailimf_message_id_new(char * mid_value) +{ + struct mailimf_message_id * message_id; + + message_id = malloc(sizeof(* message_id)); + if (message_id == NULL) + return NULL; + + message_id->mid_value = mid_value; + + return message_id; +} + +LIBETPAN_EXPORT +void mailimf_message_id_free(struct mailimf_message_id * message_id) +{ + if (message_id->mid_value != NULL) + mailimf_msg_id_free(message_id->mid_value); + free(message_id); +} + +LIBETPAN_EXPORT +struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list) +{ + struct mailimf_in_reply_to * in_reply_to; + + in_reply_to = malloc(sizeof(* in_reply_to)); + if (in_reply_to == NULL) + return NULL; + + in_reply_to->mid_list = mid_list; + + return in_reply_to; +} + +LIBETPAN_EXPORT +void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to) +{ + clist_foreach(in_reply_to->mid_list, + (clist_func) mailimf_msg_id_free, NULL); + clist_free(in_reply_to->mid_list); + free(in_reply_to); +} + +LIBETPAN_EXPORT +struct mailimf_references * mailimf_references_new(clist * mid_list) +{ + struct mailimf_references * ref; + + ref = malloc(sizeof(* ref)); + if (ref == NULL) + return NULL; + + ref->mid_list = mid_list; + + return ref; +} + +LIBETPAN_EXPORT +void mailimf_references_free(struct mailimf_references * references) +{ + clist_foreach(references->mid_list, + (clist_func) mailimf_msg_id_free, NULL); + clist_free(references->mid_list); + free(references); +} + +void mailimf_msg_id_free(char * msg_id) +{ + free(msg_id); +} + +void mailimf_id_left_free(char * id_left) +{ + free(id_left); +} + +void mailimf_id_right_free(char * id_right) +{ + free(id_right); +} + +void mailimf_no_fold_quote_free(char * nfq) +{ + free(nfq); +} + +void mailimf_no_fold_literal_free(char * nfl) +{ + free(nfl); +} + +LIBETPAN_EXPORT +struct mailimf_subject * mailimf_subject_new(char * sbj_value) +{ + struct mailimf_subject * subject; + + subject = malloc(sizeof(* subject)); + if (subject == NULL) + return NULL; + + subject->sbj_value = sbj_value; + + return subject; +} + +LIBETPAN_EXPORT +void mailimf_subject_free(struct mailimf_subject * subject) +{ + mailimf_unstructured_free(subject->sbj_value); + free(subject); +} + +LIBETPAN_EXPORT +struct mailimf_comments * mailimf_comments_new(char * cm_value) +{ + struct mailimf_comments * comments; + + comments = malloc(sizeof(* comments)); + if (comments == NULL) + return NULL; + + comments->cm_value = cm_value; + + return comments; +} + +LIBETPAN_EXPORT +void mailimf_comments_free(struct mailimf_comments * comments) +{ + mailimf_unstructured_free(comments->cm_value); + free(comments); +} + +LIBETPAN_EXPORT +struct mailimf_keywords * mailimf_keywords_new(clist * kw_list) +{ + struct mailimf_keywords * keywords; + + keywords = malloc(sizeof(* keywords)); + if (keywords == NULL) + return NULL; + + keywords->kw_list = kw_list; + + return keywords; +} + +LIBETPAN_EXPORT +void mailimf_keywords_free(struct mailimf_keywords * keywords) +{ + clist_foreach(keywords->kw_list, (clist_func) mailimf_phrase_free, NULL); + clist_free(keywords->kw_list); + free(keywords); +} + +LIBETPAN_EXPORT +struct mailimf_return * +mailimf_return_new(struct mailimf_path * ret_path) +{ + struct mailimf_return * return_path; + + return_path = malloc(sizeof(* return_path)); + if (return_path == NULL) + return NULL; + + return_path->ret_path = ret_path; + + return return_path; +} + +LIBETPAN_EXPORT +void mailimf_return_free(struct mailimf_return * return_path) +{ + mailimf_path_free(return_path->ret_path); + free(return_path); +} + +LIBETPAN_EXPORT +struct mailimf_path * mailimf_path_new(char * pt_addr_spec) +{ + struct mailimf_path * path; + + path = malloc(sizeof(* path)); + if (path == NULL) + return NULL; + + path->pt_addr_spec = pt_addr_spec; + + return path; +} + +LIBETPAN_EXPORT +void mailimf_path_free(struct mailimf_path * path) +{ + if (path->pt_addr_spec != NULL) + mailimf_addr_spec_free(path->pt_addr_spec); + free(path); +} + +LIBETPAN_EXPORT +struct mailimf_optional_field * +mailimf_optional_field_new(char * fld_name, char * fld_value) +{ + struct mailimf_optional_field * opt_field; + + opt_field = malloc(sizeof(* opt_field)); + if (opt_field == NULL) + return NULL; + + opt_field->fld_name = fld_name; + opt_field->fld_value = fld_value; + + return opt_field; +} + +LIBETPAN_EXPORT +void mailimf_optional_field_free(struct mailimf_optional_field * opt_field) +{ + mailimf_field_name_free(opt_field->fld_name); + mailimf_unstructured_free(opt_field->fld_value); + free(opt_field); +} + +void mailimf_field_name_free(char * field_name) +{ + free(field_name); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,845 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* + * $Id: mailimf_types.h,v 1.34 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILIMF_TYPES_H + +#define MAILIMF_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/libetpan-config.h> +#include <libetpan/clist.h> +#include <sys/types.h> + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + mailimf_date_time is a date + + - day is the day of month (1 to 31) + + - month (1 to 12) + + - year (4 digits) + + - hour (0 to 23) + + - min (0 to 59) + + - sec (0 to 59) + + - zone (this is the decimal value that we can read, for example: + for "-0200", the value is -200) +*/ + +struct mailimf_date_time { + int dt_day; + int dt_month; + int dt_year; + int dt_hour; + int dt_min; + int dt_sec; + int dt_zone; +}; + +LIBETPAN_EXPORT +struct mailimf_date_time * +mailimf_date_time_new(int dt_day, int dt_month, int dt_year, + int dt_hour, int dt_min, int dt_sec, int dt_zone); + +LIBETPAN_EXPORT +void mailimf_date_time_free(struct mailimf_date_time * date_time); + + + +/* this is the type of address */ + +enum { + MAILIMF_ADDRESS_ERROR, /* on parse error */ + MAILIMF_ADDRESS_MAILBOX, /* if this is a mailbox (mailbox@domain) */ + MAILIMF_ADDRESS_GROUP /* if this is a group + (group_name: address1@domain1, + address2@domain2; ) */ +}; + +/* + mailimf_address is an address + + - type can be MAILIMF_ADDRESS_MAILBOX or MAILIMF_ADDRESS_GROUP + + - mailbox is a mailbox if type is MAILIMF_ADDRESS_MAILBOX + + - group is a group if type is MAILIMF_ADDRESS_GROUP +*/ + +struct mailimf_address { + int ad_type; + union { + struct mailimf_mailbox * ad_mailbox; /* can be NULL */ + struct mailimf_group * ad_group; /* can be NULL */ + } ad_data; +}; + +LIBETPAN_EXPORT +struct mailimf_address * +mailimf_address_new(int ad_type, struct mailimf_mailbox * ad_mailbox, + struct mailimf_group * ad_group); + +LIBETPAN_EXPORT +void mailimf_address_free(struct mailimf_address * address); + + + +/* + mailimf_mailbox is a mailbox + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" <mailbox@domain>, + should be allocated with malloc() + + - addr_spec is the mailbox, for example 'mailbox@domain' + in '"name" <mailbox@domain>, should be allocated with malloc() +*/ + +struct mailimf_mailbox { + char * mb_display_name; /* can be NULL */ + char * mb_addr_spec; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_mailbox * +mailimf_mailbox_new(char * mb_display_name, char * mb_addr_spec); + +LIBETPAN_EXPORT +void mailimf_mailbox_free(struct mailimf_mailbox * mailbox); + + + +/* + mailimf_group is a group + + - display_name is the name that will be displayed for this group, + for example 'group_name' in + 'group_name: address1@domain1, address2@domain2;', should be allocated + with malloc() + + - mb_list is a list of mailboxes +*/ + +struct mailimf_group { + char * grp_display_name; /* != NULL */ + struct mailimf_mailbox_list * grp_mb_list; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_group * +mailimf_group_new(char * grp_display_name, + struct mailimf_mailbox_list * grp_mb_list); + +LIBETPAN_EXPORT +void mailimf_group_free(struct mailimf_group * group); + + + +/* + mailimf_mailbox_list is a list of mailboxes + + - list is a list of mailboxes +*/ + +struct mailimf_mailbox_list { + clist * mb_list; /* list of (struct mailimf_mailbox *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_mailbox_list * +mailimf_mailbox_list_new(clist * mb_list); + +LIBETPAN_EXPORT +void mailimf_mailbox_list_free(struct mailimf_mailbox_list * mb_list); + + + +/* + mailimf_address_list is a list of addresses + + - list is a list of addresses +*/ + +struct mailimf_address_list { + clist * ad_list; /* list of (struct mailimf_address *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_address_list * +mailimf_address_list_new(clist * ad_list); + +LIBETPAN_EXPORT +void mailimf_address_list_free(struct mailimf_address_list * addr_list); + + + + + +/* + mailimf_body is the text part of a message + + - text is the beginning of the text part, it is a substring + of an other string + + - size is the size of the text part +*/ + +struct mailimf_body { + const char * bd_text; /* != NULL */ + size_t bd_size; +}; + +LIBETPAN_EXPORT +struct mailimf_body * mailimf_body_new(const char * bd_text, size_t bd_size); + +LIBETPAN_EXPORT +void mailimf_body_free(struct mailimf_body * body); + + + + +/* + mailimf_message is the content of the message + + - msg_fields is the header fields of the message + + - msg_body is the text part of the message +*/ + +struct mailimf_message { + struct mailimf_fields * msg_fields; /* != NULL */ + struct mailimf_body * msg_body; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_message * +mailimf_message_new(struct mailimf_fields * msg_fields, + struct mailimf_body * msg_body); + +LIBETPAN_EXPORT +void mailimf_message_free(struct mailimf_message * message); + + + + +/* + mailimf_fields is a list of header fields + + - fld_list is a list of header fields +*/ + +struct mailimf_fields { + clist * fld_list; /* list of (struct mailimf_field *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_fields * mailimf_fields_new(clist * fld_list); + +LIBETPAN_EXPORT +void mailimf_fields_free(struct mailimf_fields * fields); + + + +/* this is a type of field */ + +enum { + MAILIMF_FIELD_NONE, /* on parse error */ + MAILIMF_FIELD_RETURN_PATH, /* Return-Path */ + MAILIMF_FIELD_RESENT_DATE, /* Resent-Date */ + MAILIMF_FIELD_RESENT_FROM, /* Resent-From */ + MAILIMF_FIELD_RESENT_SENDER, /* Resent-Sender */ + MAILIMF_FIELD_RESENT_TO, /* Resent-To */ + MAILIMF_FIELD_RESENT_CC, /* Resent-Cc */ + MAILIMF_FIELD_RESENT_BCC, /* Resent-Bcc */ + MAILIMF_FIELD_RESENT_MSG_ID, /* Resent-Message-ID */ + MAILIMF_FIELD_ORIG_DATE, /* Date */ + MAILIMF_FIELD_FROM, /* From */ + MAILIMF_FIELD_SENDER, /* Sender */ + MAILIMF_FIELD_REPLY_TO, /* Reply-To */ + MAILIMF_FIELD_TO, /* To */ + MAILIMF_FIELD_CC, /* Cc */ + MAILIMF_FIELD_BCC, /* Bcc */ + MAILIMF_FIELD_MESSAGE_ID, /* Message-ID */ + MAILIMF_FIELD_IN_REPLY_TO, /* In-Reply-To */ + MAILIMF_FIELD_REFERENCES, /* References */ + MAILIMF_FIELD_SUBJECT, /* Subject */ + MAILIMF_FIELD_COMMENTS, /* Comments */ + MAILIMF_FIELD_KEYWORDS, /* Keywords */ + MAILIMF_FIELD_OPTIONAL_FIELD /* other field */ +}; + +/* + mailimf_field is a field + + - fld_type is the type of the field + + - fld_data.fld_return_path is the parsed content of the Return-Path + field if type is MAILIMF_FIELD_RETURN_PATH + + - fld_data.fld_resent_date is the parsed content of the Resent-Date field + if type is MAILIMF_FIELD_RESENT_DATE + + - fld_data.fld_resent_from is the parsed content of the Resent-From field + + - fld_data.fld_resent_sender is the parsed content of the Resent-Sender field + + - fld_data.fld_resent_to is the parsed content of the Resent-To field + + - fld_data.fld_resent_cc is the parsed content of the Resent-Cc field + + - fld_data.fld_resent_bcc is the parsed content of the Resent-Bcc field + + - fld_data.fld_resent_msg_id is the parsed content of the Resent-Message-ID + field + + - fld_data.fld_orig_date is the parsed content of the Date field + + - fld_data.fld_from is the parsed content of the From field + + - fld_data.fld_sender is the parsed content of the Sender field + + - fld_data.fld_reply_to is the parsed content of the Reply-To field + + - fld_data.fld_to is the parsed content of the To field + + - fld_data.fld_cc is the parsed content of the Cc field + + - fld_data.fld_bcc is the parsed content of the Bcc field + + - fld_data.fld_message_id is the parsed content of the Message-ID field + + - fld_data.fld_in_reply_to is the parsed content of the In-Reply-To field + + - fld_data.fld_references is the parsed content of the References field + + - fld_data.fld_subject is the content of the Subject field + + - fld_data.fld_comments is the content of the Comments field + + - fld_data.fld_keywords is the parsed content of the Keywords field + + - fld_data.fld_optional_field is an other field and is not parsed +*/ + +#define LIBETPAN_MAILIMF_FIELD_UNION + +struct mailimf_field { + int fld_type; + union { + struct mailimf_return * fld_return_path; /* can be NULL */ + struct mailimf_orig_date * fld_resent_date; /* can be NULL */ + struct mailimf_from * fld_resent_from; /* can be NULL */ + struct mailimf_sender * fld_resent_sender; /* can be NULL */ + struct mailimf_to * fld_resent_to; /* can be NULL */ + struct mailimf_cc * fld_resent_cc; /* can be NULL */ + struct mailimf_bcc * fld_resent_bcc; /* can be NULL */ + struct mailimf_message_id * fld_resent_msg_id; /* can be NULL */ + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ + struct mailimf_optional_field * fld_optional_field; /* can be NULL */ + } fld_data; +}; + +LIBETPAN_EXPORT +struct mailimf_field * +mailimf_field_new(int fld_type, + struct mailimf_return * fld_return_path, + struct mailimf_orig_date * fld_resent_date, + struct mailimf_from * fld_resent_from, + struct mailimf_sender * fld_resent_sender, + struct mailimf_to * fld_resent_to, + struct mailimf_cc * fld_resent_cc, + struct mailimf_bcc * fld_resent_bcc, + struct mailimf_message_id * fld_resent_msg_id, + struct mailimf_orig_date * fld_orig_date, + struct mailimf_from * fld_from, + struct mailimf_sender * fld_sender, + struct mailimf_reply_to * fld_reply_to, + struct mailimf_to * fld_to, + struct mailimf_cc * fld_cc, + struct mailimf_bcc * fld_bcc, + struct mailimf_message_id * fld_message_id, + struct mailimf_in_reply_to * fld_in_reply_to, + struct mailimf_references * fld_references, + struct mailimf_subject * fld_subject, + struct mailimf_comments * fld_comments, + struct mailimf_keywords * fld_keywords, + struct mailimf_optional_field * fld_optional_field); + +LIBETPAN_EXPORT +void mailimf_field_free(struct mailimf_field * field); + + + +/* + mailimf_orig_date is the parsed Date field + + - date_time is the parsed date +*/ + +struct mailimf_orig_date { + struct mailimf_date_time * dt_date_time; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_orig_date * mailimf_orig_date_new(struct mailimf_date_time * + dt_date_time); + +LIBETPAN_EXPORT +void mailimf_orig_date_free(struct mailimf_orig_date * orig_date); + + + + +/* + mailimf_from is the parsed From field + + - mb_list is the parsed mailbox list +*/ + +struct mailimf_from { + struct mailimf_mailbox_list * frm_mb_list; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_from * +mailimf_from_new(struct mailimf_mailbox_list * frm_mb_list); + +LIBETPAN_EXPORT +void mailimf_from_free(struct mailimf_from * from); + + + +/* + mailimf_sender is the parsed Sender field + + - snd_mb is the parsed mailbox +*/ + +struct mailimf_sender { + struct mailimf_mailbox * snd_mb; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_sender * mailimf_sender_new(struct mailimf_mailbox * snd_mb); + +LIBETPAN_EXPORT +void mailimf_sender_free(struct mailimf_sender * sender); + + + + +/* + mailimf_reply_to is the parsed Reply-To field + + - rt_addr_list is the parsed address list + */ + +struct mailimf_reply_to { + struct mailimf_address_list * rt_addr_list; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_reply_to * +mailimf_reply_to_new(struct mailimf_address_list * rt_addr_list); + +LIBETPAN_EXPORT +void mailimf_reply_to_free(struct mailimf_reply_to * reply_to); + + + + +/* + mailimf_to is the parsed To field + + - to_addr_list is the parsed address list +*/ + +struct mailimf_to { + struct mailimf_address_list * to_addr_list; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_to * mailimf_to_new(struct mailimf_address_list * to_addr_list); + +LIBETPAN_EXPORT +void mailimf_to_free(struct mailimf_to * to); + + + + +/* + mailimf_cc is the parsed Cc field + + - cc_addr_list is the parsed addres list +*/ + +struct mailimf_cc { + struct mailimf_address_list * cc_addr_list; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_cc * mailimf_cc_new(struct mailimf_address_list * cc_addr_list); + +LIBETPAN_EXPORT +void mailimf_cc_free(struct mailimf_cc * cc); + + + + +/* + mailimf_bcc is the parsed Bcc field + + - bcc_addr_list is the parsed addres list +*/ + +struct mailimf_bcc { + struct mailimf_address_list * bcc_addr_list; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_bcc * +mailimf_bcc_new(struct mailimf_address_list * bcc_addr_list); + +LIBETPAN_EXPORT +void mailimf_bcc_free(struct mailimf_bcc * bcc); + + + +/* + mailimf_message_id is the parsed Message-ID field + + - mid_value is the message identifier +*/ + +struct mailimf_message_id { + char * mid_value; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_message_id * mailimf_message_id_new(char * mid_value); + +LIBETPAN_EXPORT +void mailimf_message_id_free(struct mailimf_message_id * message_id); + + + + +/* + mailimf_in_reply_to is the parsed In-Reply-To field + + - mid_list is the list of message identifers +*/ + +struct mailimf_in_reply_to { + clist * mid_list; /* list of (char *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_in_reply_to * mailimf_in_reply_to_new(clist * mid_list); + +LIBETPAN_EXPORT +void mailimf_in_reply_to_free(struct mailimf_in_reply_to * in_reply_to); + + + +/* + mailimf_references is the parsed References field + + - msg_id_list is the list of message identifiers + */ + +struct mailimf_references { + clist * mid_list; /* list of (char *) */ + /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_references * mailimf_references_new(clist * mid_list); + +LIBETPAN_EXPORT +void mailimf_references_free(struct mailimf_references * references); + + + +/* + mailimf_subject is the parsed Subject field + + - sbj_value is the value of the field +*/ + +struct mailimf_subject { + char * sbj_value; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_subject * mailimf_subject_new(char * sbj_value); + +LIBETPAN_EXPORT +void mailimf_subject_free(struct mailimf_subject * subject); + + +/* + mailimf_comments is the parsed Comments field + + - cm_value is the value of the field +*/ + +struct mailimf_comments { + char * cm_value; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_comments * mailimf_comments_new(char * cm_value); + +LIBETPAN_EXPORT +void mailimf_comments_free(struct mailimf_comments * comments); + + +/* + mailimf_keywords is the parsed Keywords field + + - kw_list is the list of keywords +*/ + +struct mailimf_keywords { + clist * kw_list; /* list of (char *), != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_keywords * mailimf_keywords_new(clist * kw_list); + +LIBETPAN_EXPORT +void mailimf_keywords_free(struct mailimf_keywords * keywords); + + +/* + mailimf_return is the parsed Return-Path field + + - ret_path is the parsed value of Return-Path +*/ + +struct mailimf_return { + struct mailimf_path * ret_path; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_return * +mailimf_return_new(struct mailimf_path * ret_path); + +LIBETPAN_EXPORT +void mailimf_return_free(struct mailimf_return * return_path); + + +/* + mailimf_path is the parsed value of Return-Path + + - pt_addr_spec is a mailbox +*/ + +struct mailimf_path { + char * pt_addr_spec; /* can be NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_path * mailimf_path_new(char * pt_addr_spec); + +LIBETPAN_EXPORT +void mailimf_path_free(struct mailimf_path * path); + + +/* + mailimf_optional_field is a non-parsed field + + - fld_name is the name of the field + + - fld_value is the value of the field +*/ + +struct mailimf_optional_field { + char * fld_name; /* != NULL */ + char * fld_value; /* != NULL */ +}; + +LIBETPAN_EXPORT +struct mailimf_optional_field * +mailimf_optional_field_new(char * fld_name, char * fld_value); + +LIBETPAN_EXPORT +void mailimf_optional_field_free(struct mailimf_optional_field * opt_field); + + +/* + mailimf_fields is the native structure that IMF module will use, + this module will provide an easier structure to use when parsing fields. + + mailimf_single_fields is an easier structure to get parsed fields, + rather than iteration over the list of fields + + - fld_orig_date is the parsed "Date" field + + - fld_from is the parsed "From" field + + - fld_sender is the parsed "Sender "field + + - fld_reply_to is the parsed "Reply-To" field + + - fld_to is the parsed "To" field + + - fld_cc is the parsed "Cc" field + + - fld_bcc is the parsed "Bcc" field + + - fld_message_id is the parsed "Message-ID" field + + - fld_in_reply_to is the parsed "In-Reply-To" field + + - fld_references is the parsed "References" field + + - fld_subject is the parsed "Subject" field + + - fld_comments is the parsed "Comments" field + + - fld_keywords is the parsed "Keywords" field +*/ + +struct mailimf_single_fields { + struct mailimf_orig_date * fld_orig_date; /* can be NULL */ + struct mailimf_from * fld_from; /* can be NULL */ + struct mailimf_sender * fld_sender; /* can be NULL */ + struct mailimf_reply_to * fld_reply_to; /* can be NULL */ + struct mailimf_to * fld_to; /* can be NULL */ + struct mailimf_cc * fld_cc; /* can be NULL */ + struct mailimf_bcc * fld_bcc; /* can be NULL */ + struct mailimf_message_id * fld_message_id; /* can be NULL */ + struct mailimf_in_reply_to * fld_in_reply_to; /* can be NULL */ + struct mailimf_references * fld_references; /* can be NULL */ + struct mailimf_subject * fld_subject; /* can be NULL */ + struct mailimf_comments * fld_comments; /* can be NULL */ + struct mailimf_keywords * fld_keywords; /* can be NULL */ +}; + + + + + + +/* internal use */ + +void mailimf_atom_free(char * atom); + +void mailimf_dot_atom_free(char * dot_atom); + +void mailimf_dot_atom_text_free(char * dot_atom); + +void mailimf_quoted_string_free(char * quoted_string); + +void mailimf_word_free(char * word); + +void mailimf_phrase_free(char * phrase); + +void mailimf_unstructured_free(char * unstructured); + +void mailimf_angle_addr_free(char * angle_addr); + +void mailimf_display_name_free(char * display_name); + +void mailimf_addr_spec_free(char * addr_spec); + +void mailimf_local_part_free(char * local_part); + +void mailimf_domain_free(char * domain); + +void mailimf_domain_literal_free(char * domain); + +void mailimf_msg_id_free(char * msg_id); + +void mailimf_id_left_free(char * id_left); + +void mailimf_id_right_free(char * id_right); + +void mailimf_no_fold_quote_free(char * nfq); + +void mailimf_no_fold_literal_free(char * nfl); + +void mailimf_field_name_free(char * field_name); + + + +/* these are the possible returned error codes */ + +enum { + MAILIMF_NO_ERROR = 0, + MAILIMF_ERROR_PARSE, + MAILIMF_ERROR_MEMORY, + MAILIMF_ERROR_INVAL, + MAILIMF_ERROR_FILE +}; + + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_types_helper.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_types_helper.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1656 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimf_types_helper.h" + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef _MSC_VER +# include "win_etpan.h" +#endif + +#include "mailimf.h" + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new_empty(void) +{ + clist * list; + struct mailimf_mailbox_list * mb_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + mb_list = mailimf_mailbox_list_new(list); + if (mb_list == NULL) + return NULL; + + return mb_list; +} + +int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list, + struct mailimf_mailbox * mb) +{ + int r; + + r = clist_append(mailbox_list->mb_list, mb); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list, + char * mb_str) +{ + int r; + size_t cur_token; + struct mailimf_mailbox * mb; + int res; + + cur_token = 0; + r = mailimf_mailbox_parse(mb_str, strlen(mb_str), &cur_token, &mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_mailbox_list_add(mailbox_list, mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + + return MAILIMF_NO_ERROR; + + free: + mailimf_mailbox_free(mb); + err: + return res; +} + +int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list, + char * display_name, char * address) +{ + int r; + struct mailimf_mailbox * mb; + int res; + + mb = mailimf_mailbox_new(display_name, address); + if (mb == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = mailimf_mailbox_list_add(mailbox_list, mb); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + + return MAILIMF_NO_ERROR; + + free: + mailimf_mailbox_free(mb); + err: + return res; +} + + + +struct mailimf_address_list * +mailimf_address_list_new_empty(void) +{ + clist * list; + struct mailimf_address_list * addr_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + addr_list = mailimf_address_list_new(list); + if (addr_list == NULL) + return NULL; + + return addr_list; +} + +int mailimf_address_list_add(struct mailimf_address_list * address_list, + struct mailimf_address * addr) +{ + int r; + + r = clist_append(address_list->ad_list, addr); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +int mailimf_address_list_add_parse(struct mailimf_address_list * address_list, + char * addr_str) +{ + int r; + size_t cur_token; + struct mailimf_address * addr; + int res; + + cur_token = 0; + r = mailimf_address_parse(addr_str, strlen(addr_str), &cur_token, &addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_address_list_add(address_list, addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + + return MAILIMF_NO_ERROR; + + free: + mailimf_address_free(addr); + err: + return res; +} + +int mailimf_address_list_add_mb(struct mailimf_address_list * address_list, + char * display_name, char * address) +{ + int r; + struct mailimf_mailbox * mb; + struct mailimf_address * addr; + int res; + + mb = mailimf_mailbox_new(display_name, address); + if (mb == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL); + if (addr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_mb; + } + + r = mailimf_address_list_add(address_list, addr); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_addr; + } + + return MAILIMF_NO_ERROR; + + free_addr: + mailimf_address_free(addr); + free_mb: + mailimf_mailbox_free(mb); + err: + return res; +} + + +#if 0 +struct mailimf_resent_fields_list * +mailimf_resent_fields_list_new_empty(void) +{ + clist * list; + struct mailimf_resent_fields_list * rf_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + rf_list = mailimf_resent_fields_list_new(list); + if (rf_list == NULL) + return NULL; + + return rf_list; +} + +int mailimf_resent_fields_add(struct mailimf_resent_fields_list * fields, + struct mailimf_resent_field * field) +{ + int r; + + r = clist_append(fields->list, field); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} +#endif + + +static void detach_free_common_fields(struct mailimf_orig_date * imf_date, + struct mailimf_from * imf_from, + struct mailimf_sender * imf_sender, + struct mailimf_to * imf_to, + struct mailimf_cc * imf_cc, + struct mailimf_bcc * imf_bcc, + struct mailimf_message_id * imf_msg_id) +{ + if (imf_date != NULL) { + imf_date->dt_date_time = NULL; + mailimf_orig_date_free(imf_date); + } + if (imf_from != NULL) { + imf_from->frm_mb_list = NULL; + mailimf_from_free(imf_from); + } + if (imf_sender != NULL) { + imf_sender->snd_mb = NULL; + mailimf_sender_free(imf_sender); + } + if (imf_to != NULL) { + imf_to->to_addr_list = NULL; + mailimf_to_free(imf_to); + } + if (imf_cc != NULL) { + imf_cc->cc_addr_list = NULL; + mailimf_to_free(imf_to); + } + if (imf_bcc != NULL) { + imf_bcc->bcc_addr_list = NULL; + mailimf_bcc_free(imf_bcc); + } + if (imf_msg_id != NULL) { + imf_msg_id->mid_value = NULL; + mailimf_message_id_free(imf_msg_id); + } +} + +static void detach_resent_field(struct mailimf_field * field) +{ + field->fld_type = MAILIMF_FIELD_NONE; + mailimf_field_free(field); +} + +int +mailimf_resent_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * resent_date, + struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id) +{ + struct mailimf_orig_date * imf_resent_date; + struct mailimf_from * imf_resent_from; + struct mailimf_sender * imf_resent_sender; + struct mailimf_to * imf_resent_to; + struct mailimf_cc * imf_resent_cc; + struct mailimf_bcc * imf_resent_bcc; + struct mailimf_message_id * imf_resent_msg_id; + struct mailimf_field * field; + int r; + + imf_resent_date = NULL; + imf_resent_from = NULL; + imf_resent_sender = NULL; + imf_resent_to = NULL; + imf_resent_cc = NULL; + imf_resent_bcc = NULL; + imf_resent_msg_id = NULL; + field = NULL; + + if (resent_date != NULL) { + imf_resent_date = mailimf_orig_date_new(resent_date); + if (imf_resent_date == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_DATE, + NULL /* return-path */, + imf_resent_date /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_from != NULL) { + imf_resent_from = mailimf_from_new(resent_from); + if (imf_resent_from == NULL) + goto free_field; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_FROM, + NULL /* return-path */, + NULL /* resent date */, + imf_resent_from /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_sender != NULL) { + imf_resent_sender = mailimf_sender_new(resent_sender); + if (imf_resent_sender == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_SENDER, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + imf_resent_sender /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_to != NULL) { + imf_resent_to = mailimf_to_new(resent_to); + if (imf_resent_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + imf_resent_to /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_cc != NULL) { + imf_resent_cc = mailimf_cc_new(resent_cc); + if (imf_resent_cc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_CC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + imf_resent_cc /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_bcc != NULL) { + imf_resent_bcc = mailimf_bcc_new(resent_bcc); + if (imf_resent_bcc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_BCC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + imf_resent_bcc /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (resent_msg_id != NULL) { + imf_resent_msg_id = mailimf_message_id_new(resent_msg_id); + if (imf_resent_msg_id == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_RESENT_MSG_ID, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + imf_resent_msg_id /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + return MAILIMF_NO_ERROR; + + free_field: + if (field != NULL) { + detach_resent_field(field); + mailimf_field_free(field); + } + free: + detach_free_common_fields(imf_resent_date, + imf_resent_from, + imf_resent_sender, + imf_resent_to, + imf_resent_cc, + imf_resent_bcc, + imf_resent_msg_id); + return MAILIMF_ERROR_MEMORY; +} + +struct mailimf_fields * +mailimf_resent_fields_new_with_data_all(struct mailimf_date_time * + resent_date, + struct mailimf_mailbox_list * + resent_from, + struct mailimf_mailbox * + resent_sender, + struct mailimf_address_list * + resent_to, + struct mailimf_address_list * + resent_cc, + struct mailimf_address_list * + resent_bcc, + char * resent_msg_id) +{ + struct mailimf_fields * resent_fields; + int r; + + resent_fields = mailimf_fields_new_empty(); + if (resent_fields == NULL) + goto err; + + r = mailimf_resent_fields_add_data(resent_fields, + resent_date, resent_from, + resent_sender, resent_to, + resent_cc, resent_bcc, + resent_msg_id); + if (r != MAILIMF_NO_ERROR) + goto free; + + return resent_fields; + + free: + mailimf_fields_free(resent_fields); + err: + return NULL; +} + + +struct mailimf_fields * +mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc) +{ + struct mailimf_date_time * date; + char * msg_id; + struct mailimf_fields * fields; + + date = mailimf_get_current_date(); + if (date == NULL) + goto err; + + msg_id = mailimf_get_message_id(); + if (msg_id == NULL) + goto free_date; + + fields = mailimf_resent_fields_new_with_data_all(date, + from, sender, to, cc, bcc, msg_id); + if (fields == NULL) + goto free_msg_id; + + return fields; + + free_msg_id: + free(msg_id); + free_date: + mailimf_date_time_free(date); + err: + return NULL; +} + + +struct mailimf_fields * +mailimf_fields_new_empty(void) +{ + clist * list; + struct mailimf_fields * fields_list; + + list = clist_new(); + if (list == NULL) + return NULL; + + fields_list = mailimf_fields_new(list); + if (fields_list == NULL) + return NULL; + + return fields_list; +} + +int mailimf_fields_add(struct mailimf_fields * fields, + struct mailimf_field * field) +{ + int r; + + r = clist_append(fields->fld_list, field); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +static void detach_free_fields(struct mailimf_orig_date * date, + struct mailimf_from * from, + struct mailimf_sender * sender, + struct mailimf_reply_to * reply_to, + struct mailimf_to * to, + struct mailimf_cc * cc, + struct mailimf_bcc * bcc, + struct mailimf_message_id * msg_id, + struct mailimf_in_reply_to * in_reply_to, + struct mailimf_references * references, + struct mailimf_subject * subject) +{ + detach_free_common_fields(date, + from, + sender, + to, + cc, + bcc, + msg_id); + + if (reply_to != NULL) { + reply_to->rt_addr_list = NULL; + mailimf_reply_to_free(reply_to); + } + + if (in_reply_to != NULL) { + in_reply_to->mid_list = NULL; + mailimf_in_reply_to_free(in_reply_to); + } + + if (references != NULL) { + references->mid_list = NULL; + mailimf_references_free(references); + } + + if (subject != NULL) { + subject->sbj_value = NULL; + mailimf_subject_free(subject); + } +} + + +static void detach_field(struct mailimf_field * field) +{ + field->fld_type = MAILIMF_FIELD_NONE; + mailimf_field_free(field); +} + +int mailimf_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * msg_id, + clist * in_reply_to, + clist * references, + char * subject) +{ + struct mailimf_orig_date * imf_date; + struct mailimf_from * imf_from; + struct mailimf_sender * imf_sender; + struct mailimf_reply_to * imf_reply_to; + struct mailimf_to * imf_to; + struct mailimf_cc * imf_cc; + struct mailimf_bcc * imf_bcc; + struct mailimf_message_id * imf_msg_id; + struct mailimf_references * imf_references; + struct mailimf_in_reply_to * imf_in_reply_to; + struct mailimf_subject * imf_subject; + struct mailimf_field * field; + int r; + + imf_date = NULL; + imf_from = NULL; + imf_sender = NULL; + imf_reply_to = NULL; + imf_to = NULL; + imf_cc = NULL; + imf_bcc = NULL; + imf_msg_id = NULL; + imf_references = NULL; + imf_in_reply_to = NULL; + imf_subject =NULL; + field = NULL; + + if (date != NULL) { + imf_date = mailimf_orig_date_new(date); + if (imf_date == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + imf_date /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (from != NULL) { + imf_from = mailimf_from_new(from); + if (imf_from == NULL) + goto free_field; + field = mailimf_field_new(MAILIMF_FIELD_FROM, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + imf_from /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (sender != NULL) { + imf_sender = mailimf_sender_new(sender); + if (imf_sender == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_SENDER, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + imf_sender /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (reply_to != NULL) { + imf_reply_to = mailimf_reply_to_new(reply_to); + if (imf_reply_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_REPLY_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + imf_reply_to /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (to != NULL) { + imf_to = mailimf_to_new(to); + if (imf_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + imf_to /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (cc != NULL) { + imf_cc = mailimf_cc_new(cc); + if (imf_cc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_CC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + imf_cc /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (bcc != NULL) { + imf_bcc = mailimf_bcc_new(bcc); + if (imf_bcc == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_BCC, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + imf_bcc /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (msg_id != NULL) { + imf_msg_id = mailimf_message_id_new(msg_id); + if (imf_msg_id == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + imf_msg_id /* message id */, + NULL /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (in_reply_to != NULL) { + imf_in_reply_to = mailimf_in_reply_to_new(in_reply_to); + if (imf_in_reply_to == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_IN_REPLY_TO, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + imf_in_reply_to /* in reply to */, + NULL /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (references != NULL) { + imf_references = mailimf_references_new(references); + if (imf_references == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_REFERENCES, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + imf_references /* references */, + NULL /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + if (subject != NULL) { + imf_subject = mailimf_subject_new(subject); + if (imf_subject == NULL) + goto free; + field = mailimf_field_new(MAILIMF_FIELD_SUBJECT, + NULL /* return-path */, + NULL /* resent date */, + NULL /* resent from */, + NULL /* resent sender */, + NULL /* resent to */, + NULL /* resent cc */, + NULL /* resent bcc */, + NULL /* resent msg id */, + NULL /* date */, + NULL /* from */, + NULL /* sender */, + NULL /* reply-to */, + NULL /* to */, + NULL /* cc */, + NULL /* bcc */, + NULL /* message id */, + NULL /* in reply to */, + NULL /* references */, + imf_subject /* subject */, + NULL /* comments */, + NULL /* keywords */, + NULL /* optional field */); + if (field == NULL) + goto free; + r = mailimf_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) + goto free_field; + } + + return MAILIMF_NO_ERROR; + + free_field: + if (field != NULL) { + detach_field(field); + mailimf_field_free(field); + } + free: + detach_free_fields(imf_date, + imf_from, + imf_sender, + imf_reply_to, + imf_to, + imf_cc, + imf_bcc, + imf_msg_id, + imf_in_reply_to, + imf_references, + imf_subject); + + return MAILIMF_ERROR_MEMORY; +} + +struct mailimf_fields * +mailimf_fields_new_with_data_all(struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * message_id, + clist * in_reply_to, + clist * references, + char * subject) +{ + struct mailimf_fields * fields; + int r; + + fields = mailimf_fields_new_empty(); + if (fields == NULL) + goto err; + + r = mailimf_fields_add_data(fields, + date, + from, + sender, + reply_to, + to, + cc, + bcc, + message_id, + in_reply_to, + references, + subject); + if (r != MAILIMF_NO_ERROR) + goto free; + + return fields; + + free: + mailimf_fields_free(fields); + err: + return NULL; +} + +struct mailimf_fields * +mailimf_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + clist * in_reply_to, + clist * references, + char * subject) +{ + struct mailimf_date_time * date; + char * msg_id; + struct mailimf_fields * fields; + + date = mailimf_get_current_date(); + if (date == NULL) + goto err; + + msg_id = mailimf_get_message_id(); + if (msg_id == NULL) + goto free_date; + + fields = mailimf_fields_new_with_data_all(date, + from, sender, reply_to, + to, cc, bcc, + msg_id, + in_reply_to, references, + subject); + if (fields == NULL) + goto free_msg_id; + + return fields; + + free_msg_id: + free(msg_id); + free_date: + mailimf_date_time_free(date); + err: + return NULL; +} + + + +#define MAX_MESSAGE_ID 512 + +char * mailimf_get_message_id(void) +{ + char id[MAX_MESSAGE_ID]; + time_t now; + char name[MAX_MESSAGE_ID]; + long value; + + now = time(NULL); + value = random(); + + gethostname(name, MAX_MESSAGE_ID); + snprintf(id, MAX_MESSAGE_ID, "etPan.%lx.%lx.%x@%s", + now, value, getpid(), name); + + return strdup(id); +} + + + +static time_t mkgmtime(struct tm * tmp); + + +struct mailimf_date_time * mailimf_get_current_date(void) +{ + struct tm gmt; + struct tm lt; + int off; + time_t now; + struct mailimf_date_time * date_time; + + now = time(NULL); + + if (gmtime_r(&now, &gmt) == NULL) + return NULL; + + if (localtime_r(&now, <) == NULL) + return NULL; + + off = (mkgmtime(<) - mkgmtime(&gmt)) / (60 * 60) * 100; + + date_time = mailimf_date_time_new(lt.tm_mday, lt.tm_mon + 1, lt.tm_year + 1900, + lt.tm_hour, lt.tm_min, lt.tm_sec, + off); + + return date_time; +} + + + +/* mkgmtime.c - make time corresponding to a GMT timeval struct + $Id: mailimf_types_helper.c,v 1.18 2006/10/22 20:22:06 hoa Exp $ + + * Copyright (c) 1998-2000 Carnegie Mellon University. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The name "Carnegie Mellon University" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For permission or any other legal + * details, please contact + * Office of Technology Transfer + * Carnegie Mellon University + * 5000 Forbes Avenue + * Pittsburgh, PA 15213-3890 + * (412) 268-4387, fax: (412) 268-7395 + * tech-transfer@andrew.cmu.edu + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by Computing Services + * at Carnegie Mellon University (http://www.cmu.edu/computing/)." + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * + */ +/* + * Copyright (c) 1987, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Arthur David Olson of the National Cancer Institute. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* +** Adapted from code provided by Robert Elz, who writes: +** The "best" way to do mktime I think is based on an idea of Bob +** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now). +** It does a binary search of the time_t space. Since time_t's are +** just 32 bits, its a max of 32 iterations (even at 64 bits it +** would still be very reasonable). +*/ + +/* + adapted for libEtPan! by DINH V. Hoa +*/ + +#ifndef WRONG +#define WRONG (-1) +#endif /* !defined WRONG */ + +static int tmcomp(struct tm * atmp, struct tm * btmp) +{ + register int result; + + if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && + (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && + (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && + (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && + (result = (atmp->tm_min - btmp->tm_min)) == 0) + result = atmp->tm_sec - btmp->tm_sec; + return result; +} + +static time_t mkgmtime(struct tm * tmp) +{ + register int dir; + register int bits; + register int saved_seconds; + time_t t; + struct tm yourtm, *mytm; + + yourtm = *tmp; + saved_seconds = yourtm.tm_sec; + yourtm.tm_sec = 0; + /* + ** Calculate the number of magnitude bits in a time_t + ** (this works regardless of whether time_t is + ** signed or unsigned, though lint complains if unsigned). + */ + for (bits = 0, t = 1; t > 0; ++bits, t <<= 1) + ; + /* + ** If time_t is signed, then 0 is the median value, + ** if time_t is unsigned, then 1 << bits is median. + */ + t = (t < 0) ? 0 : ((time_t) 1 << bits); + for ( ; ; ) { + mytm = gmtime(&t); + dir = tmcomp(mytm, &yourtm); + if (dir != 0) { + if (bits-- < 0) + return WRONG; + if (bits < 0) + --t; + else if (dir > 0) + t -= (time_t) 1 << bits; + else t += (time_t) 1 << bits; + continue; + } + break; + } + t += saved_seconds; + return t; +} + + + + + + + +void mailimf_single_fields_init(struct mailimf_single_fields * single_fields, + struct mailimf_fields * fields) +{ + clistiter * cur; + + memset(single_fields, 0, sizeof(struct mailimf_single_fields)); + + cur = clist_begin(fields->fld_list); + while (cur != NULL) { + struct mailimf_field * field; + + field = clist_content(cur); + + switch (field->fld_type) { + case MAILIMF_FIELD_ORIG_DATE: + if (single_fields->fld_orig_date == NULL) + single_fields->fld_orig_date = field->fld_data.fld_orig_date; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_FROM: + if (single_fields->fld_from == NULL) { + single_fields->fld_from = field->fld_data.fld_from; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_from->frm_mb_list->mb_list, + field->fld_data.fld_from->frm_mb_list->mb_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_SENDER: + if (single_fields->fld_sender == NULL) + single_fields->fld_sender = field->fld_data.fld_sender; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_REPLY_TO: + if (single_fields->fld_reply_to == NULL) { + single_fields->fld_reply_to = field->fld_data.fld_reply_to; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_reply_to->rt_addr_list->ad_list, + field->fld_data.fld_reply_to->rt_addr_list->ad_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_TO: + if (single_fields->fld_to == NULL) { + single_fields->fld_to = field->fld_data.fld_to; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_to->to_addr_list->ad_list, + field->fld_data.fld_to->to_addr_list->ad_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_CC: + if (single_fields->fld_cc == NULL) { + single_fields->fld_cc = field->fld_data.fld_cc; + cur = clist_next(cur); + } + else { + clist_concat(single_fields->fld_cc->cc_addr_list->ad_list, + field->fld_data.fld_cc->cc_addr_list->ad_list); + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + break; + case MAILIMF_FIELD_BCC: + if (single_fields->fld_bcc == NULL) { + single_fields->fld_bcc = field->fld_data.fld_bcc; + cur = clist_next(cur); + } + else { + if (field->fld_data.fld_bcc->bcc_addr_list != NULL) { + if (single_fields->fld_bcc->bcc_addr_list == NULL) { + single_fields->fld_bcc->bcc_addr_list = field->fld_data.fld_bcc->bcc_addr_list; + field->fld_data.fld_bcc->bcc_addr_list = NULL; + } + else { + clist_concat(single_fields->fld_bcc->bcc_addr_list->ad_list, + field->fld_data.fld_bcc->bcc_addr_list->ad_list); + } + mailimf_field_free(field); + cur = clist_delete(fields->fld_list, cur); + } + else { + cur = clist_next(cur); + } + } + break; + case MAILIMF_FIELD_MESSAGE_ID: + if (single_fields->fld_message_id == NULL) + single_fields->fld_message_id = field->fld_data.fld_message_id; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + if (single_fields->fld_in_reply_to == NULL) + single_fields->fld_in_reply_to = field->fld_data.fld_in_reply_to; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_REFERENCES: + if (single_fields->fld_references == NULL) + single_fields->fld_references = field->fld_data.fld_references; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_SUBJECT: + if (single_fields->fld_subject == NULL) + single_fields->fld_subject = field->fld_data.fld_subject; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_COMMENTS: + if (single_fields->fld_comments == NULL) + single_fields->fld_comments = field->fld_data.fld_comments; + cur = clist_next(cur); + break; + case MAILIMF_FIELD_KEYWORDS: + if (single_fields->fld_keywords == NULL) + single_fields->fld_keywords = field->fld_data.fld_keywords; + cur = clist_next(cur); + break; + default: + cur = clist_next(cur); + break; + } + } +} + + +struct mailimf_single_fields * +mailimf_single_fields_new(struct mailimf_fields * fields) +{ + struct mailimf_single_fields * single_fields; + + single_fields = malloc(sizeof(struct mailimf_single_fields)); + if (single_fields == NULL) + goto err; + + mailimf_single_fields_init(single_fields, fields); + + return single_fields; + + err: + return NULL; +} + +void mailimf_single_fields_free(struct mailimf_single_fields * + single_fields) +{ + free(single_fields); +} + +struct mailimf_field * mailimf_field_new_custom(char * name, char * value) +{ + struct mailimf_optional_field * opt_field; + struct mailimf_field * field; + + opt_field = mailimf_optional_field_new(name, value); + if (opt_field == NULL) + goto err; + + field = mailimf_field_new(MAILIMF_FIELD_OPTIONAL_FIELD, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, opt_field); + if (field == NULL) + goto free_opt_field; + + return field; + + free_opt_field: + mailimf_optional_field_free(opt_field); + err: + return NULL; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_types_helper.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_types_helper.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,370 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_types_helper.h,v 1.13 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILIMF_TYPES_HELPER + +#define MAILIMF_TYPES_HELPER + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailimf_types.h> + +/* + IMPORTANT NOTE: + + All allocation functions will take as argument allocated data + and will store these data in the structure they will allocate. + Data should be persistant during all the use of the structure + and will be freed by the free function of the structure + + allocation functions will return NULL on failure +*/ + +/* + mailimf_mailbox_list_new_empty creates an empty list of mailboxes +*/ + +struct mailimf_mailbox_list * +mailimf_mailbox_list_new_empty(void); + +/* + mailimf_mailbox_list_add adds a mailbox to the list of mailboxes + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_mailbox_list_add(struct mailimf_mailbox_list * mailbox_list, + struct mailimf_mailbox * mb); + +/* + mailimf_mailbox_list_add_parse parse the given string + into a mailimf_mailbox structure and adds it to the list of mailboxes + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_mailbox_list_add_parse(struct mailimf_mailbox_list * mailbox_list, + char * mb_str); + +/* + mailimf_mailbox creates a mailimf_mailbox structure with the given + arguments and adds it to the list of mailboxes + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" <mailbox@domain>, + should be allocated with malloc() + + - address is the mailbox, for example 'mailbox@domain' + in '"name" <mailbox@domain>, should be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_mailbox_list_add_mb(struct mailimf_mailbox_list * mailbox_list, + char * display_name, char * address); + +/* + mailimf_address_list_new_empty creates an empty list of addresses +*/ + +struct mailimf_address_list * +mailimf_address_list_new_empty(void); + +/* + mailimf_address_list_add adds a mailbox to the list of addresses + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_address_list_add(struct mailimf_address_list * address_list, + struct mailimf_address * addr); + +/* + mailimf_address_list_add_parse parse the given string + into a mailimf_address structure and adds it to the list of addresses + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_address_list_add_parse(struct mailimf_address_list * address_list, + char * addr_str); + +/* + mailimf_address_list_add_mb creates a mailbox mailimf_address + with the given arguments and adds it to the list of addresses + + - display_name is the name that will be displayed for this mailbox, + for example 'name' in '"name" <mailbox@domain>, + should be allocated with malloc() + + - address is the mailbox, for example 'mailbox@domain' + in '"name" <mailbox@domain>, should be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_address_list_add_mb(struct mailimf_address_list * address_list, + char * display_name, char * address); + +/* + mailimf_resent_fields_add_data adds a set of resent fields in the + given mailimf_fields structure. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param resent_msg_id sould be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int +mailimf_resent_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * resent_date, + struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +/* + mailimf_resent_fields_new_with_data_all creates a new mailimf_fields + structure with a set of resent fields + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param resent_msg_id sould be allocated with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +struct mailimf_fields * +mailimf_resent_fields_new_with_data_all(struct mailimf_date_time * + resent_date, struct mailimf_mailbox_list * resent_from, + struct mailimf_mailbox * resent_sender, + struct mailimf_address_list * resent_to, + struct mailimf_address_list * resent_cc, + struct mailimf_address_list * resent_bcc, + char * resent_msg_id); + +/* + mailimf_resent_fields_new_with_data_all creates a new mailimf_fields + structure with a set of resent fields. + Resent-Date and Resent-Message-ID fields will be generated for you. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +struct mailimf_fields * +mailimf_resent_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc); + +/* + this function creates a new mailimf_fields structure with no fields +*/ + +struct mailimf_fields * +mailimf_fields_new_empty(void); + + +/* + this function adds a field to the mailimf_fields structure + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_fields_add(struct mailimf_fields * fields, + struct mailimf_field * field); + + +/* + mailimf_fields_add_data adds a set of fields in the + given mailimf_fields structure. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param msg_id sould be allocated with malloc() + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +int mailimf_fields_add_data(struct mailimf_fields * fields, + struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * msg_id, + clist * in_reply_to, + clist * references, + char * subject); + +/* + mailimf_fields_new_with_data_all creates a new mailimf_fields + structure with a set of fields + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param message_id sould be allocated with malloc() + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +struct mailimf_fields * +mailimf_fields_new_with_data_all(struct mailimf_date_time * date, + struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + char * message_id, + clist * in_reply_to, + clist * references, + char * subject); + +/* + mailimf_fields_new_with_data creates a new mailimf_fields + structure with a set of fields + Date and Message-ID fields will be generated for you. + + if you don't want a given field in the set to be added in the list + of fields, you can give NULL as argument + + @param subject should be allocated with malloc() + @param in_reply_to each elements of this list should be allocated + with malloc() + @param references each elements of this list should be allocated + with malloc() + + @return MAILIMF_NO_ERROR will be returned on success, + other code will be returned otherwise +*/ + +struct mailimf_fields * +mailimf_fields_new_with_data(struct mailimf_mailbox_list * from, + struct mailimf_mailbox * sender, + struct mailimf_address_list * reply_to, + struct mailimf_address_list * to, + struct mailimf_address_list * cc, + struct mailimf_address_list * bcc, + clist * in_reply_to, + clist * references, + char * subject); + +/* + this function returns an allocated message identifier to + use in a Message-ID or Resent-Message-ID field +*/ + +char * mailimf_get_message_id(void); + +/* + this function returns a mailimf_date_time structure to + use in a Date or Resent-Date field +*/ + +struct mailimf_date_time * mailimf_get_current_date(void); + + +/* + mailimf_single_fields_init fills a mailimf_single_fields structure + with the content of a mailimf_fields structure +*/ + +void mailimf_single_fields_init(struct mailimf_single_fields * single_fields, + struct mailimf_fields * fields); + +/* + mailimf_single_fields_new creates a new mailimf_single_fields and + fills the structure with mailimf_fields +*/ + +struct mailimf_single_fields * +mailimf_single_fields_new(struct mailimf_fields * fields); + +void mailimf_single_fields_free(struct mailimf_single_fields * + single_fields); + +/* + mailimf_field_new_custom creates a new field of type optional + + @param name should be allocated with malloc() + @param value should be allocated with malloc() +*/ + +struct mailimf_field * mailimf_field_new_custom(char * name, char * value); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,2021 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write.c,v 1.26 2004/11/21 21:53:37 hoa Exp $ + */ + +#include "mailimf_write.h" + +#include <time.h> +#include <string.h> +#include <ctype.h> + +#define MAX_MAIL_COL 72 + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define MAX_VALID_IMF_LINE 998 + +static int mailimf_orig_date_write(FILE * f, int * col, + struct mailimf_orig_date * date); +static int mailimf_date_time_write(FILE * f, int * col, + struct mailimf_date_time * date_time); +static int mailimf_from_write(FILE * f, int * col, + struct mailimf_from * from); +static int mailimf_sender_write(FILE * f, int * col, + struct mailimf_sender * sender); +static int mailimf_reply_to_write(FILE * f, int * col, + struct mailimf_reply_to * reply_to); +static int mailimf_to_write(FILE * f, int * col, + struct mailimf_to * to); +static int mailimf_cc_write(FILE * f, int * col, + struct mailimf_cc * to); +static int mailimf_bcc_write(FILE * f, int * col, + struct mailimf_bcc * to); +static int mailimf_message_id_write(FILE * f, int * col, + struct mailimf_message_id * message_id); +static int mailimf_msg_id_list_write(FILE * f, int * col, + clist * list); +static int mailimf_in_reply_to_write(FILE * f, int * col, + struct mailimf_in_reply_to * + in_reply_to); +static int mailimf_references_write(FILE * f, int * col, + struct mailimf_references * references); +static int mailimf_subject_write(FILE * f, int * col, + struct mailimf_subject * subject); + +static int mailimf_address_write(FILE * f, int * col, + struct mailimf_address * addr); +static int mailimf_group_write(FILE * f, int * col, + struct mailimf_group * group); + +static int mailimf_mailbox_write(FILE * f, int * col, + struct mailimf_mailbox * mb); + +static int mailimf_comments_write(FILE * f, int * col, + struct mailimf_comments * comments); + +static int mailimf_optional_field_write(FILE * f, int * col, + struct mailimf_optional_field * field); + +static int mailimf_keywords_write(FILE * f, int * col, + struct mailimf_keywords * keywords); + +static int mailimf_return_write(FILE * f, int * col, + struct mailimf_return * return_path); + +static int mailimf_path_write(FILE * f, int * col, + struct mailimf_path * path); + +static int mailimf_resent_date_write(FILE * f, int * col, + struct mailimf_orig_date * date); + +static int mailimf_resent_from_write(FILE * f, int * col, + struct mailimf_from * from); + +static int mailimf_resent_sender_write(FILE * f, int * col, + struct mailimf_sender * sender); + +static int mailimf_resent_to_write(FILE * f, int * col, + struct mailimf_to * to); + +static int mailimf_resent_cc_write(FILE * f, int * col, + struct mailimf_cc * cc); + +static int mailimf_resent_bcc_write(FILE * f, int * col, + struct mailimf_bcc * bcc); + +static int +mailimf_resent_msg_id_write(FILE * f, int * col, + struct mailimf_message_id * message_id); + + + +/* ************************ */ + +#if 0 +int mailimf_string_write(FILE * f, int * col, + char * str, size_t length) +{ + int r; + + if (length != 0) { + r = fwrite(str, sizeof(char), length, f); + if (r < 0) + return MAILIMF_ERROR_FILE; + * col += length; + } + + return MAILIMF_NO_ERROR; +} +#endif + +#define CRLF "\r\n" +#define HEADER_FOLD "\r\n " + +static inline int flush_buf(FILE * f, const char * str, size_t length) +{ + if (length != 0) { + int r; + + r = fwrite(str, 1, length, f); + if (r == 0) + return MAILIMF_ERROR_FILE; + } + return MAILIMF_NO_ERROR; +} + +#define CUT_AT_MAX_VALID_IMF_LINE + +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length) +{ + int r; + size_t count; + const char * block_begin; + const char * p; + int done; + + p = str; + block_begin = str; + count = 0; + + while (length > 0) { +#ifdef CUT_AT_MAX_VALID_IMF_LINE + if (count >= 998) { + /* + cut lines at maximum valid length for internet message + format standard (currently RFC 2822) + + This should not happen. + In case there are some lines larger than 998 in body, + the encoding must be changed into base64 or quoted-printable + so that wrapping to 72 columns is done. + */ + + r = flush_buf(f, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f); + if (r == 0) + return MAILIMF_ERROR_FILE; + + count = 0; + block_begin = p; + + * col = 0; + } +#endif + switch (* p) { + case '\n': + r = flush_buf(f, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p ++; + length --; + count = 0; + block_begin = p; + + * col = 0; + break; + + case '\r': + done = 0; + if (length >= 2) { + if (* (p + 1) == '\n') { + r = flush_buf(f, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p += 2; + length -= 2; + count = 0; + block_begin = p; + + * col = 0; + + done = 1; + } + } + if (!done) { + r = flush_buf(f, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = fwrite(CRLF, 1, sizeof(CRLF) - 1, f); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p ++; + length --; + count = 0; + block_begin = p; + + * col = 0; + } + break; + + default: + p ++; + count ++; + length --; + break; + } + } + + r = flush_buf(f, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + * col += count; + + return MAILIMF_NO_ERROR; +} + +#if 0 +int mailimf_header_string_write(FILE * f, int * col, + char * str, size_t length) +{ + char * p; + char * block_begin; + int current_col; + char * last_cut; + int r; + int first; + + if (* col + length < MAX_MAIL_COL) + return mailimf_string_write(f, col, str, length); + + first = 1; + p = str; + block_begin = p; + last_cut = block_begin; + current_col = * col; + + while (1) { + if (current_col >= MAX_MAIL_COL) { + /* if we reach the maximum recommanded size of line */ + if (last_cut == block_begin) { + /* if we could not find any place to cut */ + if (first) { + /* fold the header */ + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + current_col = * col + p - block_begin; + first = 0; + } + else { + /* cut the header */ + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + first = 0; + block_begin = p; + last_cut = block_begin; + current_col = * col + p - block_begin; + } + } + else { + /* if we found a place to cut */ + r = mailimf_string_write(f, col, block_begin, last_cut - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + first = 0; + block_begin = last_cut; + last_cut = block_begin; + current_col = * col + p - block_begin; + continue; + } + } + else { + if (length == 0) + break; + + switch (* p) { + case ' ': + case '\t': + last_cut = p; + current_col ++; + break; + + case '\r': + case '\n': + current_col = 0; + break; + + default: + current_col ++; + break; + } + + p ++; + length --; + } + } + + return mailimf_string_write(f, col, block_begin, p - block_begin); +} +#endif + +#if 0 +enum { + STATE_LOWER_72, + STATE_LOWER_72_CUT, + STATE_EQUAL_72, + STATE_LOWER_998, + STATE_EQUAL_998, +}; + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length) +{ + int state; + const char * p; + const char * block_begin; + size_t size; + const char * cut; + int r; + + if (* col < MAX_MAIL_COL) + state = STATE_LOWER_72_CUT; + else if (* col == MAX_MAIL_COL) + state = STATE_EQUAL_72; + else if (* col < MAX_VALID_IMF_LINE) + state = STATE_LOWER_998; + else + state = STATE_EQUAL_998; + + p = str; + block_begin = p; + size = * col; + cut = p; + + while (length > 0) { + switch (state) { + case STATE_LOWER_72: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + break; + + case ' ': + case '\t': + cut = p; + p ++; + length --; + size ++; + state = STATE_LOWER_72_CUT; + break; + + default: + if (size < MAX_MAIL_COL - 1) { + p ++; + length --; + size ++; + } + else { + state = STATE_EQUAL_72; + p ++; + length --; + size ++; + } + break; + } + break; /* end of STATE_LOWER_72 */ + + case STATE_LOWER_72_CUT: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + cut = p; + p ++; + length --; + size ++; + break; + + default: + if (size < MAX_MAIL_COL) { + p ++; + length --; + size ++; + } + else { + r = mailimf_string_write(f, col, block_begin, cut - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = cut; + if ((* block_begin == ' ') || (* block_begin == '\t')) + block_begin ++; + size = p - block_begin + * col; + state = STATE_LOWER_72; + } + break; + } + break; /* end of STATE_LOWER_72_CUT */ + + case STATE_EQUAL_72: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: + p ++; + length --; + size ++; + state = STATE_LOWER_998; + break; + } + break; /* end of STATE_EQUAL_72 */ + + case STATE_LOWER_998: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: + if (size < MAX_VALID_IMF_LINE - 1) { + p ++; + length --; + size ++; + } + else { + p ++; + length --; + size = 0; + state = STATE_EQUAL_998; + } + break; + } + break; /* end of STATE_LOWER_998 */ + + case STATE_EQUAL_998: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: +#ifdef CUT_AT_MAX_VALID_IMF_LINE + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; +#else + p ++; + length --; + size ++; +#endif + break; + } + break; /* end of STATE_EQUAL_998 */ + } + } + + r = mailimf_string_write(f, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +enum { + STATE_BEGIN, + STATE_WORD, + STATE_SPACE, +}; + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length) +{ + int state; + const char * p; + const char * word_begin; + const char * word_end; + const char * next_word; + int first; + + state = STATE_BEGIN; + + p = str; + word_begin = p; + word_end = p; + next_word = p; + first = 1; + + while (length > 0) { + switch (state) { + case STATE_BEGIN: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + p ++; + length --; + break; + + default: + word_begin = p; + state = STATE_WORD; + break; + } + break; + + case STATE_SPACE: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + p ++; + length --; + break; + + default: + word_begin = p; + state = STATE_WORD; + break; + } + break; + + case STATE_WORD: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + if (p - word_begin + (* col) + 1 > MAX_MAIL_COL) + mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + else { + if (!first) + mailimf_string_write(f, col, " ", 1); + } + first = 0; + mailimf_string_write(f, col, word_begin, p - word_begin); + state = STATE_SPACE; + break; + + default: + if (p - word_begin + (* col) >= MAX_VALID_IMF_LINE) { + mailimf_string_write(f, col, word_begin, p - word_begin); + mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + word_begin = p; + } + p ++; + length --; + break; + } + break; + } + } + + if (state == STATE_WORD) { + if (p - word_begin + (* col) >= MAX_MAIL_COL) + mailimf_string_write(f, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + else { + if (!first) + mailimf_string_write(f, col, " ", 1); + } + first = 0; + mailimf_string_write(f, col, word_begin, p - word_begin); + } + + return MAILIMF_NO_ERROR; +} + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + int r; + struct mailimf_field * field; + + field = clist_content(cur); + if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) { + r = mailimf_field_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + return MAILIMF_NO_ERROR; +} + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + int r; + + r = mailimf_field_write(f, col, clist_content(cur)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + +#if 0 +int mailimf_unparsed_fields_write(FILE * f, int * col, + struct mailimf_unparsed_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->list) ; cur != NULL ; cur = cur->next) { + int r; + + r = mailimf_optional_field_write(f, col, cur->data); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} +#endif + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field) +{ + int r; + + switch (field->fld_type) { + case MAILIMF_FIELD_RETURN_PATH: + r = mailimf_return_write(f, col, field->fld_data.fld_return_path); + break; + case MAILIMF_FIELD_RESENT_DATE: + r = mailimf_resent_date_write(f, col, field->fld_data.fld_resent_date); + break; + case MAILIMF_FIELD_RESENT_FROM: + r = mailimf_resent_from_write(f, col, field->fld_data.fld_resent_from); + break; + case MAILIMF_FIELD_RESENT_SENDER: + r = mailimf_resent_sender_write(f, col, field->fld_data.fld_resent_sender); + break; + case MAILIMF_FIELD_RESENT_TO: + r = mailimf_resent_to_write(f, col, field->fld_data.fld_resent_to); + break; + case MAILIMF_FIELD_RESENT_CC: + r = mailimf_resent_cc_write(f, col, field->fld_data.fld_resent_cc); + break; + case MAILIMF_FIELD_RESENT_BCC: + r = mailimf_resent_bcc_write(f, col, field->fld_data.fld_resent_bcc); + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + r = mailimf_resent_msg_id_write(f, col, field->fld_data.fld_resent_msg_id); + break; + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_orig_date_write(f, col, field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + r = mailimf_from_write(f, col, field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_sender_write(f, col, field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_reply_to_write(f, col, field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + r = mailimf_to_write(f, col, field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + r = mailimf_cc_write(f, col, field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + r = mailimf_bcc_write(f, col, field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_message_id_write(f, col, field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_in_reply_to_write(f, col, field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_references_write(f, col, field->fld_data.fld_references); + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_subject_write(f, col, field->fld_data.fld_subject); + break; + case MAILIMF_FIELD_COMMENTS: + r = mailimf_comments_write(f, col, field->fld_data.fld_comments); + break; + case MAILIMF_FIELD_KEYWORDS: + r = mailimf_keywords_write(f, col, field->fld_data.fld_keywords); + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + r = mailimf_optional_field_write(f, col, field->fld_data.fld_optional_field); + break; + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_orig_date_write(FILE * f, int * col, + struct mailimf_orig_date * date) +{ + int r; + + r = mailimf_string_write(f, col, "Date: ", 6); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_date_time_write(f, col, date->dt_date_time); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +#define MAX_DATE_STR 256 + +/* 0 = Sunday */ +/* y > 1752 */ + +static int dayofweek(int year, int month, int day) +{ + static int offset[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; + + year -= month < 3; + + return (year + year/4 - year/100 + year/400 + offset[month-1] + day) % 7; +} + +static const char * week_of_day_str[] = { "Sun", "Mon", "Tue", "Wed", "Thu", + "Fri", "Sat"}; +static const char * month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +static int mailimf_date_time_write(FILE * f, int * col, + struct mailimf_date_time * date_time) +{ + int r; + char date_str[MAX_DATE_STR]; +#if 0 + struct tm tmval; + time_t timeval; +#endif + int wday; + +#if 0 + tmval.tm_sec = date_time->sec; + tmval.tm_min = date_time->min; + tmval.tm_hour = date_time->hour; + tmval.tm_sec = date_time->sec; + tmval.tm_mday = date_time->day; + tmval.tm_mon = date_time->month - 1; + tmval.tm_year = date_time->year - 1900; + tmval.tm_isdst = 1; + + timeval = mktime(&tmval); + + localtime_r(&timeval, &tmval); +#endif + + wday = dayofweek(date_time->dt_year, date_time->dt_month, date_time->dt_day); + + snprintf(date_str, MAX_DATE_STR, "%s, %i %s %i %02i:%02i:%02i %+05i", + week_of_day_str[wday], date_time->dt_day, + month_str[date_time->dt_month - 1], + date_time->dt_year, date_time->dt_hour, + date_time->dt_min, date_time->dt_sec, + date_time->dt_zone); + + r = mailimf_string_write(f, col, date_str, strlen(date_str)); + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailimf_from_write(FILE * f, int * col, + struct mailimf_from * from) +{ + int r; + + r = mailimf_string_write(f, col, "From: ", 6); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_list_write(f, col, from->frm_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_sender_write(FILE * f, int * col, + struct mailimf_sender * sender) +{ + int r; + + r = mailimf_string_write(f, col, "Sender: ", 8); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_write(f, col, sender->snd_mb); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_reply_to_write(FILE * f, int * col, + struct mailimf_reply_to * reply_to) +{ + int r; + + r = mailimf_string_write(f, col, "Reply-To: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write(f, col, reply_to->rt_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_to_write(FILE * f, int * col, + struct mailimf_to * to) +{ + int r; + + r = mailimf_string_write(f, col, "To: ", 4); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write(f, col, to->to_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_cc_write(FILE * f, int * col, + struct mailimf_cc * cc) +{ + int r; + + r = mailimf_string_write(f, col, "Cc: ", 4); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write(f, col, cc->cc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_bcc_write(FILE * f, int * col, + struct mailimf_bcc * bcc) +{ + int r; + + r = mailimf_string_write(f, col, "Bcc: ", 5); + if (r != MAILIMF_NO_ERROR) + return r; + + if (bcc->bcc_addr_list != NULL) { + r = mailimf_address_list_write(f, col, bcc->bcc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_message_id_write(FILE * f, int * col, + struct mailimf_message_id * message_id) +{ + int r; + + r = mailimf_string_write(f, col, "Message-ID: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, + message_id->mid_value, + strlen(message_id->mid_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_msg_id_list_write(FILE * f, int * col, clist * mid_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(mid_list) ; cur != NULL ; cur = clist_next(cur)) { + char * msgid; + size_t len; + + msgid = clist_content(cur); + len = strlen(msgid); + + /* + XXX - if this is the first message ID, don't fold. + This is a workaround for a bug of old versions of INN. + */ + if (!first) { + if (* col > 1) { + + if (* col + len >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + first = TRUE; + } + } + } + + if (!first) { + r = mailimf_string_write(f, col, " ", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_string_write(f, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, msgid, len); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_in_reply_to_write(FILE * f, int * col, + struct mailimf_in_reply_to * in_reply_to) +{ + int r; + + r = mailimf_string_write(f, col, "In-Reply-To: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_list_write(f, col, in_reply_to->mid_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_references_write(FILE * f, int * col, + struct mailimf_references * references) +{ + int r; + + r = mailimf_string_write(f, col, "References: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_list_write(f, col, references->mid_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + + +static int mailimf_subject_write(FILE * f, int * col, + struct mailimf_subject * subject) +{ + int r; + + r = mailimf_string_write(f, col, "Subject: ", 9); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write(f, col, + subject->sbj_value, strlen(subject->sbj_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_address_write(f, col, addr); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_address_write(FILE * f, int * col, + struct mailimf_address * addr) +{ + int r; + + switch(addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = mailimf_mailbox_write(f, col, addr->ad_data.ad_mailbox); + if (r != MAILIMF_NO_ERROR) + return r; + + break; + + case MAILIMF_ADDRESS_GROUP: + r = mailimf_group_write(f, col, addr->ad_data.ad_group); + if (r != MAILIMF_NO_ERROR) + return r; + + break; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_group_write(FILE * f, int * col, + struct mailimf_group * group) +{ + int r; + + r = mailimf_header_string_write(f, col, group->grp_display_name, + strlen(group->grp_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ": ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + if (group->grp_mb_list != NULL) { + r = mailimf_mailbox_list_write(f, col, group->grp_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, ";", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_mailbox_write(f, col, mb); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len) +{ + int r; + size_t i; + + fputc('\"', f); + for(i = 0 ; i < len ; i ++) { + switch (string[i]) { + case '\\': + case '\"': + r = fputc('\\', f); + if (r < 0) + return MAILIMF_ERROR_FILE; + r = fputc(string[i], f); + if (r < 0) + return MAILIMF_ERROR_FILE; + (* col) += 2; + break; + + default: + r = fputc(string[i], f); + if (r < 0) + return MAILIMF_ERROR_FILE; + (* col) ++; + break; + } + } + fputc('\"', f); + + return MAILIMF_NO_ERROR; +} + + +/* +static int +atext = ALPHA / DIGIT / ; Any character except controls, + "!" / "#" / ; SP, and specials. + "$" / "%" / ; Used for atoms + "&" / "'" / + "*" / "+" / + "-" / "/" / + "=" / "?" / + "^" / "_" / + "`" / "{" / + "|" / "}" / + "~" +*/ + +static int is_atext(const char * s) +{ + const char * p; + + for(p = s ; * p != 0 ; p ++) { + if (isalpha((unsigned char) * p)) + continue; + if (isdigit((unsigned char) * p)) + continue; + switch (*p) { + case ' ': + case '\t': + case '!': + case '#': + case '$': + case '%': + case '&': + case '\'': + case '*': + case '+': + case '-': + case '/': + case '=': + case '?': + case '^': + case '_': + case '`': + case '{': + case '|': + case '}': + case '~': + break; + default: + return 0; + } + } + + return 1; +} + +static int mailimf_mailbox_write(FILE * f, int * col, + struct mailimf_mailbox * mb) +{ + int r; + int do_fold; + +#if 0 + if (* col > 1) { + + if (mb->mb_display_name != NULL) { + if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + } +#endif + + if (mb->mb_display_name) { + + if (is_atext(mb->mb_display_name)) { + r = mailimf_header_string_write(f, col, mb->mb_display_name, + strlen(mb->mb_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + if (mb->mb_display_name != NULL) { + if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + if (strlen(mb->mb_display_name) > MAX_VALID_IMF_LINE / 2) + return MAILIMF_ERROR_INVAL; + + r = mailimf_quoted_string_write(f, col, mb->mb_display_name, + strlen(mb->mb_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + do_fold = 0; + if (* col > 1) { + + if (* col + strlen(mb->mb_addr_spec) + 3 >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + do_fold = 1; + } + } + + if (do_fold) + r = mailimf_string_write(f, col, "<", 1); + else + r = mailimf_string_write(f, col, " <", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, mb->mb_addr_spec, + strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, + mb->mb_addr_spec, strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + + return MAILIMF_NO_ERROR; +} + +static int mailimf_comments_write(FILE * f, int * col, + struct mailimf_comments * comments) +{ + int r; + + r = mailimf_string_write(f, col, "Comments: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write(f, col, + comments->cm_value, strlen(comments->cm_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_optional_field_write(FILE * f, int * col, + struct mailimf_optional_field * field) +{ + int r; + + if (strlen(field->fld_name) + 2 > MAX_VALID_IMF_LINE) + return MAILIMF_ERROR_INVAL; + + r = mailimf_string_write(f, col, field->fld_name, strlen(field->fld_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ": ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write(f, col, field->fld_value, + strlen(field->fld_value)); + if (r != MAILIMF_NO_ERROR) + return r; + +#if 0 + /* XXX parsing debug */ + mailimf_string_write(f, col, " (X)", 4); +#endif + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_keywords_write(FILE * f, int * col, + struct mailimf_keywords * keywords) +{ + int r; + clistiter * cur; + int first; + + r = mailimf_string_write(f, col, "Keywords: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + first = TRUE; + + for(cur = clist_begin(keywords->kw_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * keyword; + size_t len; + + keyword = clist_content(cur); + len = strlen(keyword); + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + +#if 0 + if (* col > 1) { + + if (* col + len >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } +#endif + + r = mailimf_header_string_write(f, col, keyword, len); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +#if 0 +static int mailimf_delivering_info_write(FILE * f, int * col, + struct mailimf_delivering_info * info) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(info->received_fields) ; + cur != NULL ; cur = cur->next) { + struct mailimf_trace_resent_fields * field; + + field = cur->data; + + r = mailimf_trace_resent_fields_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int +mailimf_trace_resent_fields_write(FILE * f, int * col, + struct mailimf_trace_resent_fields * field) +{ + int r; + + if (field->return_path != NULL) { + r = mailimf_return_write(f, col, field->return_path); + if (r != MAILIMF_NO_ERROR) + return r; + } + + if (field->resent_fields != NULL) { + r = mailimf_resent_fields_write(f, col, field->resent_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} +#endif + +static int mailimf_return_write(FILE * f, int * col, + struct mailimf_return * return_path) +{ + int r; + + r = mailimf_string_write(f, col, "Return-Path: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_path_write(f, col, return_path->ret_path); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_path_write(FILE * f, int * col, + struct mailimf_path * path) +{ + int r; + + r = mailimf_string_write(f, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, path->pt_addr_spec, + strlen(path->pt_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +#if 0 +static int mailimf_resent_fields_write(FILE * f, int * col, + struct mailimf_resent_fields_list * + resent_fields) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(resent_fields->list) ; cur != NULL ; cur = cur->next) { + struct mailimf_resent_field * field; + + field = cur->data; + + r = mailimf_resent_field_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + + +static int mailimf_resent_field_write(FILE * f, int * col, + struct mailimf_resent_field * + resent_field) +{ + int r; + + switch (resent_field->type) { + case MAILIMF_RESENT_FIELD_DATE: + r = mailimf_resent_date_write(f, col, resent_field->resent_date); + break; + + case MAILIMF_RESENT_FIELD_FROM: + r = mailimf_resent_from_write(f, col, resent_field->resent_from); + break; + + case MAILIMF_RESENT_FIELD_SENDER: + r = mailimf_resent_sender_write(f, col, resent_field->resent_sender); + break; + + case MAILIMF_RESENT_FIELD_TO: + r = mailimf_resent_to_write(f, col, resent_field->resent_to); + break; + + case MAILIMF_RESENT_FIELD_CC: + r = mailimf_resent_cc_write(f, col, resent_field->resent_cc); + break; + + case MAILIMF_RESENT_FIELD_BCC: + r = mailimf_resent_bcc_write(f, col, resent_field->resent_bcc); + break; + + case MAILIMF_RESENT_FIELD_MSG_ID: + r = mailimf_resent_msg_id_write(f, col, resent_field->resent_msg_id); + break; + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +static int mailimf_resent_date_write(FILE * f, int * col, + struct mailimf_orig_date * date) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-Date: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_date_time_write(f, col, date->dt_date_time); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_from_write(FILE * f, int * col, + struct mailimf_from * from) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-From: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_list_write(f, col, from->frm_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_sender_write(FILE * f, int * col, + struct mailimf_sender * sender) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-Sender: ", 15); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_write(f, col, sender->snd_mb); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_to_write(FILE * f, int * col, + struct mailimf_to * to) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-To: ", 11); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write(f, col, to->to_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_resent_cc_write(FILE * f, int * col, + struct mailimf_cc * cc) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-Cc: ", 11); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write(f, col, cc->cc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_resent_bcc_write(FILE * f, int * col, + struct mailimf_bcc * bcc) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-Bcc: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + if (bcc->bcc_addr_list != NULL) { + r = mailimf_address_list_write(f, col, bcc->bcc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int +mailimf_resent_msg_id_write(FILE * f, int * col, + struct mailimf_message_id * message_id) +{ + int r; + + r = mailimf_string_write(f, col, "Resent-Message-ID: ", 19); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, + message_id->mid_value, strlen(message_id->mid_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,134 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write.h,v 1.13 2004/11/21 21:53:37 hoa Exp $ + */ + +#ifndef MAILIMF_WRITE_H + +#define MAILIMF_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> +#include <libetpan/mailimf_types.h> + +/* + mailimf_string_write writes a string to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write writes the fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write writes only some fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write writes a field to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write writes a string that is quoted + to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ + +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len); + +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list); + +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write writes a header value and fold the header + if needed. + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_file.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_file.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,157 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write_file.c,v 1.3 2005/06/01 12:22:18 smarinier Exp $ + */ + +#include "mailimf_write_file.h" +#include "mailimf_write_generic.h" + +static int do_write(void * data, const char * str, size_t length) +{ + FILE * f; + + f = data; + + return fwrite(str, 1, length, f); +} + +LIBETPAN_EXPORT +int mailimf_string_write_file(FILE * f, int * col, + const char * str, size_t length) +{ + return mailimf_string_write_driver(do_write, f, col, str, length); +} + +LIBETPAN_EXPORT +int mailimf_fields_write_file(FILE * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_fields_write_driver(do_write, f, col, fields); +} + +LIBETPAN_EXPORT +int mailimf_envelope_fields_write_file(FILE * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_envelope_fields_write_driver(do_write, f, col, fields); +} + +LIBETPAN_EXPORT +int mailimf_field_write_file(FILE * f, int * col, + struct mailimf_field * field) +{ + return mailimf_field_write_driver(do_write, f, col, field); +} + +LIBETPAN_EXPORT +int mailimf_quoted_string_write_file(FILE * f, int * col, + const char * string, size_t len) +{ + return mailimf_quoted_string_write_driver(do_write, f, col, string, len); +} + +LIBETPAN_EXPORT +int mailimf_address_list_write_file(FILE * f, int * col, + struct mailimf_address_list * addr_list) +{ + return mailimf_address_list_write_driver(do_write, f, col, addr_list); +} + +LIBETPAN_EXPORT +int mailimf_mailbox_list_write_file(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list) +{ + return mailimf_mailbox_list_write_driver(do_write, f, col, mb_list); +} + +LIBETPAN_EXPORT +int mailimf_header_string_write_file(FILE * f, int * col, + const char * str, size_t length) +{ + return mailimf_header_string_write_driver(do_write, f, col, str, length); +} + + +/* binary compatibility with 0.34 - begin */ + +#ifdef MAILIMF_WRITE_COMPATIBILITY +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length) +{ + return mailimf_string_write_file(f, col, str, length); +} + +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_fields_write_file(f, col, fields); +} + +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_envelope_fields_write_file(f, col, fields); +} + +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field) +{ + return mailimf_field_write_file(f, col, field); +} + +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len) +{ + return mailimf_quoted_string_write_file(f, col, string, len); +} + +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list) +{ + return mailimf_address_list_write_file(f, col, addr_list); +} + +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list) +{ + return mailimf_mailbox_list_write_file(f, col, mb_list); +} + +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length) +{ + return mailimf_header_string_write_file(f, col, str, length); +} +#endif + +/* binary compatibility with 0.34 - end */ Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_file.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_file.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,180 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write_file.h,v 1.3 2005/06/01 12:22:18 smarinier Exp $ + */ + +#ifndef MAILIMF_WRITE_H + +#define MAILIMF_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> +#include <libetpan/mailimf_types.h> + +#define MAILIMF_WRITE_COMPATIBILITY + +/* + mailimf_string_write_file writes a string to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ +LIBETPAN_EXPORT +int mailimf_string_write_file(FILE * f, int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write_file writes the fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ +LIBETPAN_EXPORT +int mailimf_fields_write_file(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write_file writes only some fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ +LIBETPAN_EXPORT +int mailimf_envelope_fields_write_file(FILE * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write_file writes a field to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ +LIBETPAN_EXPORT +int mailimf_field_write_file(FILE * f, int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write_file writes a string that is quoted + to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ +LIBETPAN_EXPORT +int mailimf_quoted_string_write_file(FILE * f, int * col, + const char * string, size_t len); + +LIBETPAN_EXPORT +int mailimf_address_list_write_file(FILE * f, int * col, + struct mailimf_address_list * addr_list); + +LIBETPAN_EXPORT +int mailimf_mailbox_list_write_file(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write_file writes a header value and fold the header + if needed. + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +LIBETPAN_EXPORT +int mailimf_header_string_write_file(FILE * f, int * col, + const char * str, size_t length); + + + +/* binary compatibility with 0.34 - begin */ + +#ifdef MAILIMF_WRITE_COMPATIBILITY +LIBETPAN_EXPORT +int mailimf_string_write(FILE * f, int * col, + const char * str, size_t length); + +LIBETPAN_EXPORT +int mailimf_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +LIBETPAN_EXPORT +int mailimf_envelope_fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +LIBETPAN_EXPORT +int mailimf_field_write(FILE * f, int * col, + struct mailimf_field * field); + +LIBETPAN_EXPORT +int mailimf_quoted_string_write(FILE * f, int * col, + const char * string, size_t len); + +LIBETPAN_EXPORT +int mailimf_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list); + +LIBETPAN_EXPORT +int mailimf_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list); + +LIBETPAN_EXPORT +int mailimf_header_string_write(FILE * f, int * col, + const char * str, size_t length); +#endif + +/* binary compatibility with 0.34 - end */ + + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_generic.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_generic.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,2032 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write_generic.c,v 1.3 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimf_write_generic.h" + +#include <time.h> +#include <string.h> +#include <ctype.h> + +#define MAX_MAIL_COL 72 + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define MAX_VALID_IMF_LINE 998 + +static int mailimf_orig_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_orig_date * date); +static int mailimf_date_time_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_date_time * date_time); +static int mailimf_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_from * from); +static int mailimf_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_sender * sender); +static int mailimf_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_reply_to * reply_to); +static int mailimf_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_to * to); +static int mailimf_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_cc * to); +static int mailimf_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_bcc * to); +static int mailimf_message_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_message_id * message_id); +static int mailimf_msg_id_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + clist * list); +static int mailimf_in_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_in_reply_to * + in_reply_to); +static int mailimf_references_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_references * references); +static int mailimf_subject_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_subject * subject); + +static int mailimf_address_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_address * addr); +static int mailimf_group_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_group * group); + +static int mailimf_mailbox_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_mailbox * mb); + +static int mailimf_comments_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_comments * comments); + +static int mailimf_optional_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_optional_field * field); + +static int mailimf_keywords_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_keywords * keywords); + +static int mailimf_return_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_return * return_path); + +static int mailimf_path_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_path * path); + +static int mailimf_resent_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_orig_date * date); + +static int mailimf_resent_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_from * from); + +static int mailimf_resent_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_sender * sender); + +static int mailimf_resent_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_to * to); + +static int mailimf_resent_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_cc * cc); + +static int mailimf_resent_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_bcc * bcc); + +static int +mailimf_resent_msg_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_message_id * message_id); + + + +/* ************************ */ + +#if 0 +int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + char * str, size_t length) +{ + int r; + + if (length != 0) { + r = fwrite(str, sizeof(char), length, f); + if (r < 0) + return MAILIMF_ERROR_FILE; + * col += length; + } + + return MAILIMF_NO_ERROR; +} +#endif + +#define CRLF "\r\n" +#define HEADER_FOLD "\r\n " + +static inline int flush_buf(int (* do_write)(void *, const char *, size_t), void * data, const char * str, size_t length) +{ + if (length != 0) { + int r; + + if (length > 0) { + r = do_write(data, str, length); + if (r == 0) + return MAILIMF_ERROR_FILE; + } + } + return MAILIMF_NO_ERROR; +} + +#define CUT_AT_MAX_VALID_IMF_LINE + +int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * str, size_t length) +{ + int r; + size_t count; + const char * block_begin; + const char * p; + int done; + + p = str; + block_begin = str; + count = 0; + + while (length > 0) { +#ifdef CUT_AT_MAX_VALID_IMF_LINE + if (count >= 998) { + /* + cut lines at maximum valid length for internet message + format standard (currently RFC 2822) + + This should not happen. + In case there are some lines larger than 998 in body, + the encoding must be changed into base64 or quoted-printable + so that wrapping to 72 columns is done. + */ + + r = flush_buf(do_write, data, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = do_write(data, CRLF, sizeof(CRLF) - 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + + count = 0; + block_begin = p; + + * col = 0; + } +#endif + switch (* p) { + case '\n': + r = flush_buf(do_write, data, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = do_write(data, CRLF, sizeof(CRLF) - 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p ++; + length --; + count = 0; + block_begin = p; + + * col = 0; + break; + + case '\r': + done = 0; + if (length >= 2) { + if (* (p + 1) == '\n') { + r = flush_buf(do_write, data, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = do_write(data, CRLF, sizeof(CRLF) - 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p += 2; + length -= 2; + count = 0; + block_begin = p; + + * col = 0; + + done = 1; + } + } + if (!done) { + r = flush_buf(do_write, data, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + + r = do_write(data, CRLF, sizeof(CRLF) - 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + + p ++; + length --; + count = 0; + block_begin = p; + + * col = 0; + } + break; + + default: + p ++; + count ++; + length --; + break; + } + } + + r = flush_buf(do_write, data, block_begin, count); + if (r != MAILIMF_NO_ERROR) + return r; + * col += count; + + return MAILIMF_NO_ERROR; +} + +#if 0 +int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + char * str, size_t length) +{ + char * p; + char * block_begin; + int current_col; + char * last_cut; + int r; + int first; + + if (* col + length < MAX_MAIL_COL) + return mailimf_string_write_driver(do_write, data, col, str, length); + + first = 1; + p = str; + block_begin = p; + last_cut = block_begin; + current_col = * col; + + while (1) { + if (current_col >= MAX_MAIL_COL) { + /* if we reach the maximum recommanded size of line */ + if (last_cut == block_begin) { + /* if we could not find any place to cut */ + if (first) { + /* fold the header */ + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + current_col = * col + p - block_begin; + first = 0; + } + else { + /* cut the header */ + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + first = 0; + block_begin = p; + last_cut = block_begin; + current_col = * col + p - block_begin; + } + } + else { + /* if we found a place to cut */ + r = mailimf_string_write_driver(do_write, data, col, block_begin, last_cut - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + first = 0; + block_begin = last_cut; + last_cut = block_begin; + current_col = * col + p - block_begin; + continue; + } + } + else { + if (length == 0) + break; + + switch (* p) { + case ' ': + case '\t': + last_cut = p; + current_col ++; + break; + + case '\r': + case '\n': + current_col = 0; + break; + + default: + current_col ++; + break; + } + + p ++; + length --; + } + } + + return mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); +} +#endif + +#if 0 +enum { + STATE_LOWER_72, + STATE_LOWER_72_CUT, + STATE_EQUAL_72, + STATE_LOWER_998, + STATE_EQUAL_998, +}; + +int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * str, size_t length) +{ + int state; + const char * p; + const char * block_begin; + size_t size; + const char * cut; + int r; + + if (* col < MAX_MAIL_COL) + state = STATE_LOWER_72_CUT; + else if (* col == MAX_MAIL_COL) + state = STATE_EQUAL_72; + else if (* col < MAX_VALID_IMF_LINE) + state = STATE_LOWER_998; + else + state = STATE_EQUAL_998; + + p = str; + block_begin = p; + size = * col; + cut = p; + + while (length > 0) { + switch (state) { + case STATE_LOWER_72: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + break; + + case ' ': + case '\t': + cut = p; + p ++; + length --; + size ++; + state = STATE_LOWER_72_CUT; + break; + + default: + if (size < MAX_MAIL_COL - 1) { + p ++; + length --; + size ++; + } + else { + state = STATE_EQUAL_72; + p ++; + length --; + size ++; + } + break; + } + break; /* end of STATE_LOWER_72 */ + + case STATE_LOWER_72_CUT: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + cut = p; + p ++; + length --; + size ++; + break; + + default: + if (size < MAX_MAIL_COL) { + p ++; + length --; + size ++; + } + else { + r = mailimf_string_write_driver(do_write, data, col, block_begin, cut - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = cut; + if ((* block_begin == ' ') || (* block_begin == '\t')) + block_begin ++; + size = p - block_begin + * col; + state = STATE_LOWER_72; + } + break; + } + break; /* end of STATE_LOWER_72_CUT */ + + case STATE_EQUAL_72: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: + p ++; + length --; + size ++; + state = STATE_LOWER_998; + break; + } + break; /* end of STATE_EQUAL_72 */ + + case STATE_LOWER_998: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: + if (size < MAX_VALID_IMF_LINE - 1) { + p ++; + length --; + size ++; + } + else { + p ++; + length --; + size = 0; + state = STATE_EQUAL_998; + } + break; + } + break; /* end of STATE_LOWER_998 */ + + case STATE_EQUAL_998: + switch (* p) { + case '\r': + case '\n': + p ++; + length --; + size = 0; + state = STATE_LOWER_72; + break; + + case ' ': + case '\t': + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; + break; + + default: +#ifdef CUT_AT_MAX_VALID_IMF_LINE + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + r = mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + if (r != MAILIMF_NO_ERROR) + return r; + p ++; + length --; + block_begin = p; + size = p - block_begin + * col; + state = STATE_LOWER_72; +#else + p ++; + length --; + size ++; +#endif + break; + } + break; /* end of STATE_EQUAL_998 */ + } + } + + r = mailimf_string_write_driver(do_write, data, col, block_begin, p - block_begin); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +enum { + STATE_BEGIN, + STATE_WORD, + STATE_SPACE +}; + +int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * str, size_t length) +{ + int state; + const char * p; + const char * word_begin; + const char * word_end; + const char * next_word; + int first; + + state = STATE_BEGIN; + + p = str; + word_begin = p; + word_end = p; + next_word = p; + first = 1; + + while (length > 0) { + switch (state) { + case STATE_BEGIN: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + p ++; + length --; + break; + + default: + word_begin = p; + state = STATE_WORD; + break; + } + break; + + case STATE_SPACE: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + p ++; + length --; + break; + + default: + word_begin = p; + state = STATE_WORD; + break; + } + break; + + case STATE_WORD: + switch (* p) { + case '\r': + case '\n': + case ' ': + case '\t': + if (p - word_begin + (* col) + 1 > MAX_MAIL_COL) + mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + else { + if (!first) + mailimf_string_write_driver(do_write, data, col, " ", 1); + } + first = 0; + mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin); + state = STATE_SPACE; + break; + + default: + if (p - word_begin + (* col) >= MAX_VALID_IMF_LINE) { + mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin); + mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + word_begin = p; + } + p ++; + length --; + break; + } + break; + } + } + + if (state == STATE_WORD) { + if (p - word_begin + (* col) >= MAX_MAIL_COL) + mailimf_string_write_driver(do_write, data, col, HEADER_FOLD, + sizeof(HEADER_FOLD) - 1); + else { + if (!first) + mailimf_string_write_driver(do_write, data, col, " ", 1); + } + first = 0; + mailimf_string_write_driver(do_write, data, col, word_begin, p - word_begin); + } + + return MAILIMF_NO_ERROR; +} + +int mailimf_envelope_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + int r; + struct mailimf_field * field; + + field = clist_content(cur); + if (field->fld_type != MAILIMF_FIELD_OPTIONAL_FIELD) { + r = mailimf_field_write_driver(do_write, data, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + return MAILIMF_NO_ERROR; +} + +int mailimf_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + int r; + + r = mailimf_field_write_driver(do_write, data, col, clist_content(cur)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + +#if 0 +int mailimf_unparsed_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_unparsed_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->list) ; cur != NULL ; cur = cur->next) { + int r; + + r = mailimf_optional_field_write_driver(do_write, data, col, cur->data); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} +#endif + +int mailimf_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_field * field) +{ + int r; + + switch (field->fld_type) { + case MAILIMF_FIELD_RETURN_PATH: + r = mailimf_return_write_driver(do_write, data, col, field->fld_data.fld_return_path); + break; + case MAILIMF_FIELD_RESENT_DATE: + r = mailimf_resent_date_write_driver(do_write, data, col, field->fld_data.fld_resent_date); + break; + case MAILIMF_FIELD_RESENT_FROM: + r = mailimf_resent_from_write_driver(do_write, data, col, field->fld_data.fld_resent_from); + break; + case MAILIMF_FIELD_RESENT_SENDER: + r = mailimf_resent_sender_write_driver(do_write, data, col, field->fld_data.fld_resent_sender); + break; + case MAILIMF_FIELD_RESENT_TO: + r = mailimf_resent_to_write_driver(do_write, data, col, field->fld_data.fld_resent_to); + break; + case MAILIMF_FIELD_RESENT_CC: + r = mailimf_resent_cc_write_driver(do_write, data, col, field->fld_data.fld_resent_cc); + break; + case MAILIMF_FIELD_RESENT_BCC: + r = mailimf_resent_bcc_write_driver(do_write, data, col, field->fld_data.fld_resent_bcc); + break; + case MAILIMF_FIELD_RESENT_MSG_ID: + r = mailimf_resent_msg_id_write_driver(do_write, data, col, field->fld_data.fld_resent_msg_id); + break; + case MAILIMF_FIELD_ORIG_DATE: + r = mailimf_orig_date_write_driver(do_write, data, col, field->fld_data.fld_orig_date); + break; + case MAILIMF_FIELD_FROM: + r = mailimf_from_write_driver(do_write, data, col, field->fld_data.fld_from); + break; + case MAILIMF_FIELD_SENDER: + r = mailimf_sender_write_driver(do_write, data, col, field->fld_data.fld_sender); + break; + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_reply_to_write_driver(do_write, data, col, field->fld_data.fld_reply_to); + break; + case MAILIMF_FIELD_TO: + r = mailimf_to_write_driver(do_write, data, col, field->fld_data.fld_to); + break; + case MAILIMF_FIELD_CC: + r = mailimf_cc_write_driver(do_write, data, col, field->fld_data.fld_cc); + break; + case MAILIMF_FIELD_BCC: + r = mailimf_bcc_write_driver(do_write, data, col, field->fld_data.fld_bcc); + break; + case MAILIMF_FIELD_MESSAGE_ID: + r = mailimf_message_id_write_driver(do_write, data, col, field->fld_data.fld_message_id); + break; + case MAILIMF_FIELD_IN_REPLY_TO: + r = mailimf_in_reply_to_write_driver(do_write, data, col, field->fld_data.fld_in_reply_to); + break; + case MAILIMF_FIELD_REFERENCES: + r = mailimf_references_write_driver(do_write, data, col, field->fld_data.fld_references); + break; + case MAILIMF_FIELD_SUBJECT: + r = mailimf_subject_write_driver(do_write, data, col, field->fld_data.fld_subject); + break; + case MAILIMF_FIELD_COMMENTS: + r = mailimf_comments_write_driver(do_write, data, col, field->fld_data.fld_comments); + break; + case MAILIMF_FIELD_KEYWORDS: + r = mailimf_keywords_write_driver(do_write, data, col, field->fld_data.fld_keywords); + break; + case MAILIMF_FIELD_OPTIONAL_FIELD: + r = mailimf_optional_field_write_driver(do_write, data, col, field->fld_data.fld_optional_field); + break; + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_orig_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_orig_date * date) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Date: ", 6); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_date_time_write_driver(do_write, data, col, date->dt_date_time); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +#define MAX_DATE_STR 256 + +/* 0 = Sunday */ +/* y > 1752 */ + +static int dayofweek(int year, int month, int day) +{ + static int offset[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; + + year -= month < 3; + + return (year + year/4 - year/100 + year/400 + offset[month-1] + day) % 7; +} + +static const char * week_of_day_str[] = { "Sun", "Mon", "Tue", "Wed", "Thu", + "Fri", "Sat"}; +static const char * month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +static int mailimf_date_time_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_date_time * date_time) +{ + int r; + char date_str[MAX_DATE_STR]; +#if 0 + struct tm tmval; + time_t timeval; +#endif + int wday; + +#if 0 + tmval.tm_sec = date_time->sec; + tmval.tm_min = date_time->min; + tmval.tm_hour = date_time->hour; + tmval.tm_sec = date_time->sec; + tmval.tm_mday = date_time->day; + tmval.tm_mon = date_time->month - 1; + tmval.tm_year = date_time->year - 1900; + tmval.tm_isdst = 1; + + timeval = mktime(&tmval); + + localtime_r(&timeval, &tmval); +#endif + + wday = dayofweek(date_time->dt_year, date_time->dt_month, date_time->dt_day); + + snprintf(date_str, MAX_DATE_STR, "%s, %i %s %i %02i:%02i:%02i %+05i", + week_of_day_str[wday], date_time->dt_day, + month_str[date_time->dt_month - 1], + date_time->dt_year, date_time->dt_hour, + date_time->dt_min, date_time->dt_sec, + date_time->dt_zone); + + r = mailimf_string_write_driver(do_write, data, col, date_str, strlen(date_str)); + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailimf_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_from * from) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "From: ", 6); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_list_write_driver(do_write, data, col, from->frm_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_sender * sender) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Sender: ", 8); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_write_driver(do_write, data, col, sender->snd_mb); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_reply_to * reply_to) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Reply-To: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write_driver(do_write, data, col, reply_to->rt_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_to * to) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "To: ", 4); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write_driver(do_write, data, col, to->to_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_cc * cc) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Cc: ", 4); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write_driver(do_write, data, col, cc->cc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_bcc * bcc) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Bcc: ", 5); + if (r != MAILIMF_NO_ERROR) + return r; + + if (bcc->bcc_addr_list != NULL) { + r = mailimf_address_list_write_driver(do_write, data, col, bcc->bcc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_message_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_message_id * message_id) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Message-ID: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, + message_id->mid_value, + strlen(message_id->mid_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_msg_id_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, clist * mid_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(mid_list) ; cur != NULL ; cur = clist_next(cur)) { + char * msgid; + size_t len; + + msgid = clist_content(cur); + len = strlen(msgid); + + /* + XXX - if this is the first message ID, don't fold. + This is a workaround for a bug of old versions of INN. + */ + if (!first) { + if (* col > 1) { + + if (* col + len >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + first = TRUE; + } + } + } + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, " ", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, msgid, len); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_in_reply_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_in_reply_to * in_reply_to) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "In-Reply-To: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_list_write_driver(do_write, data, col, in_reply_to->mid_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_references_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_references * references) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "References: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_msg_id_list_write_driver(do_write, data, col, references->mid_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + + +static int mailimf_subject_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_subject * subject) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Subject: ", 9); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write_driver(do_write, data, col, + subject->sbj_value, strlen(subject->sbj_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +int mailimf_address_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_address_write_driver(do_write, data, col, addr); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_address_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_address * addr) +{ + int r; + + switch(addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = mailimf_mailbox_write_driver(do_write, data, col, addr->ad_data.ad_mailbox); + if (r != MAILIMF_NO_ERROR) + return r; + + break; + + case MAILIMF_ADDRESS_GROUP: + r = mailimf_group_write_driver(do_write, data, col, addr->ad_data.ad_group); + if (r != MAILIMF_NO_ERROR) + return r; + + break; + } + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_group_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_group * group) +{ + int r; + + r = mailimf_header_string_write_driver(do_write, data, col, group->grp_display_name, + strlen(group->grp_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ": ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + if (group->grp_mb_list != NULL) { + r = mailimf_mailbox_list_write_driver(do_write, data, col, group->grp_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, ";", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + +int mailimf_mailbox_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + int first; + + first = TRUE; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = clist_content(cur); + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + r = mailimf_mailbox_write_driver(do_write, data, col, mb); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +int mailimf_quoted_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * string, size_t len) +{ + int r; + size_t i; + + r = do_write(data, "\"", 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + for(i = 0 ; i < len ; i ++) { + switch (string[i]) { + case '\\': + case '\"': + r = do_write(data, "\\", 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + r = do_write(data, &string[i], 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + (* col) += 2; + break; + + default: + r = do_write(data, &string[i], 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + (* col) ++; + break; + } + } + r = do_write(data, "\"", 1); + if (r == 0) + return MAILIMF_ERROR_FILE; + + return MAILIMF_NO_ERROR; +} + + +/* +static int +atext = ALPHA / DIGIT / ; Any character except controls, + "!" / "#" / ; SP, and specials. + "$" / "%" / ; Used for atoms + "&" / "'" / + "*" / "+" / + "-" / "/" / + "=" / "?" / + "^" / "_" / + "`" / "{" / + "|" / "}" / + "~" +*/ + +static int is_atext(const char * s) +{ + const char * p; + + for(p = s ; * p != 0 ; p ++) { + if (isalpha((unsigned char) * p)) + continue; + if (isdigit((unsigned char) * p)) + continue; + switch (*p) { + case ' ': + case '\t': + case '!': + case '#': + case '$': + case '%': + case '&': + case '\'': + case '*': + case '+': + case '-': + case '/': + case '=': + case '?': + case '^': + case '_': + case '`': + case '{': + case '|': + case '}': + case '~': + break; + default: + return 0; + } + } + + return 1; +} + +static int mailimf_mailbox_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_mailbox * mb) +{ + int r; + int do_fold; + +#if 0 + if (* col > 1) { + + if (mb->mb_display_name != NULL) { + if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + } +#endif + + if (mb->mb_display_name) { + + if (is_atext(mb->mb_display_name)) { + r = mailimf_header_string_write_driver(do_write, data, col, mb->mb_display_name, + strlen(mb->mb_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + if (mb->mb_display_name != NULL) { + if (* col + strlen(mb->mb_display_name) >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + if (strlen(mb->mb_display_name) > MAX_VALID_IMF_LINE / 2) + return MAILIMF_ERROR_INVAL; + + r = mailimf_quoted_string_write_driver(do_write, data, col, mb->mb_display_name, + strlen(mb->mb_display_name)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + do_fold = 0; + if (* col > 1) { + + if (* col + strlen(mb->mb_addr_spec) + 3 >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + do_fold = 1; + } + } + + if (do_fold) + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + else + r = mailimf_string_write_driver(do_write, data, col, " <", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, mb->mb_addr_spec, + strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, + mb->mb_addr_spec, strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + } + + + return MAILIMF_NO_ERROR; +} + +static int mailimf_comments_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_comments * comments) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Comments: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write_driver(do_write, data, col, + comments->cm_value, strlen(comments->cm_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_optional_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_optional_field * field) +{ + int r; + + if (strlen(field->fld_name) + 2 > MAX_VALID_IMF_LINE) + return MAILIMF_ERROR_INVAL; + + r = mailimf_string_write_driver(do_write, data, col, field->fld_name, strlen(field->fld_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ": ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_header_string_write_driver(do_write, data, col, field->fld_value, + strlen(field->fld_value)); + if (r != MAILIMF_NO_ERROR) + return r; + +#if 0 + /* XXX parsing debug */ + mailimf_string_write_driver(do_write, data, col, " (X)", 4); +#endif + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_keywords_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_keywords * keywords) +{ + int r; + clistiter * cur; + int first; + + r = mailimf_string_write_driver(do_write, data, col, "Keywords: ", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + first = TRUE; + + for(cur = clist_begin(keywords->kw_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * keyword; + size_t len; + + keyword = clist_content(cur); + len = strlen(keyword); + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + +#if 0 + if (* col > 1) { + + if (* col + len >= MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } +#endif + + r = mailimf_header_string_write_driver(do_write, data, col, keyword, len); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +#if 0 +static int mailimf_delivering_info_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_delivering_info * info) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(info->received_fields) ; + cur != NULL ; cur = cur->next) { + struct mailimf_trace_resent_fields * field; + + field = cur->data; + + r = mailimf_trace_resent_fields_write_driver(do_write, data, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + +static int +mailimf_trace_resent_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_trace_resent_fields * field) +{ + int r; + + if (field->return_path != NULL) { + r = mailimf_return_write_driver(do_write, data, col, field->return_path); + if (r != MAILIMF_NO_ERROR) + return r; + } + + if (field->resent_fields != NULL) { + r = mailimf_resent_fields_write_driver(do_write, data, col, field->resent_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} +#endif + +static int mailimf_return_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_return * return_path) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Return-Path: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_path_write_driver(do_write, data, col, return_path->ret_path); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_path_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_path * path) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, path->pt_addr_spec, + strlen(path->pt_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +#if 0 +static int mailimf_resent_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_resent_fields_list * + resent_fields) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(resent_fields->list) ; cur != NULL ; cur = cur->next) { + struct mailimf_resent_field * field; + + field = cur->data; + + r = mailimf_resent_field_write_driver(do_write, data, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + + + +static int mailimf_resent_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_resent_field * + resent_field) +{ + int r; + + switch (resent_field->type) { + case MAILIMF_RESENT_FIELD_DATE: + r = mailimf_resent_date_write_driver(do_write, data, col, resent_field->resent_date); + break; + + case MAILIMF_RESENT_FIELD_FROM: + r = mailimf_resent_from_write_driver(do_write, data, col, resent_field->resent_from); + break; + + case MAILIMF_RESENT_FIELD_SENDER: + r = mailimf_resent_sender_write_driver(do_write, data, col, resent_field->resent_sender); + break; + + case MAILIMF_RESENT_FIELD_TO: + r = mailimf_resent_to_write_driver(do_write, data, col, resent_field->resent_to); + break; + + case MAILIMF_RESENT_FIELD_CC: + r = mailimf_resent_cc_write_driver(do_write, data, col, resent_field->resent_cc); + break; + + case MAILIMF_RESENT_FIELD_BCC: + r = mailimf_resent_bcc_write_driver(do_write, data, col, resent_field->resent_bcc); + break; + + case MAILIMF_RESENT_FIELD_MSG_ID: + r = mailimf_resent_msg_id_write_driver(do_write, data, col, resent_field->resent_msg_id); + break; + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} +#endif + +static int mailimf_resent_date_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_orig_date * date) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-Date: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_date_time_write_driver(do_write, data, col, date->dt_date_time); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_from_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_from * from) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-From: ", 13); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_list_write_driver(do_write, data, col, from->frm_mb_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_sender_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_sender * sender) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-Sender: ", 15); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_mailbox_write_driver(do_write, data, col, sender->snd_mb); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailimf_resent_to_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_to * to) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-To: ", 11); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write_driver(do_write, data, col, to->to_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_resent_cc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_cc * cc) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-Cc: ", 11); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_address_list_write_driver(do_write, data, col, cc->cc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int mailimf_resent_bcc_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_bcc * bcc) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-Bcc: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + if (bcc->bcc_addr_list != NULL) { + r = mailimf_address_list_write_driver(do_write, data, col, bcc->bcc_addr_list); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + + +static int +mailimf_resent_msg_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailimf_message_id * message_id) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Resent-Message-ID: ", 19); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, + message_id->mid_value, strlen(message_id->mid_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_generic.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_generic.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,142 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write_generic.h,v 1.2 2004/11/21 21:53:37 hoa Exp $ + */ + +#ifndef MAILIMF_WRITE_GENERIC_H + +#define MAILIMF_WRITE_GENERIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> +#include <libetpan/mailimf_types.h> + +/* + mailimf_string_write writes a string to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write writes the fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write writes only some fields to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_envelope_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write writes a field to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ + +int mailimf_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write writes a string that is quoted + to a given stream + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ + +int mailimf_quoted_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + const char * string, size_t len); + +int mailimf_address_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_address_list * addr_list); + +int mailimf_mailbox_list_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write writes a header value and fold the header + if needed. + + @param f is the stream + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_header_string_write_driver(int (* do_write)(void *, const char *, size_t), void * data, + int * col, + const char * str, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_mem.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_mem.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,98 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write_mem.c,v 1.2 2004/11/21 21:53:37 hoa Exp $ + */ + +#include "mailimf_write_mem.h" +#include "mailimf_write_generic.h" + +static int do_write(void * data, const char * str, size_t length) +{ + MMAPString * f; + + f = data; + + if (mmap_string_append_len(f, str, length) == NULL) + return 0; + else + return length; +} + +int mailimf_string_write_mem(MMAPString * f, int * col, + const char * str, size_t length) +{ + return mailimf_string_write_driver(do_write, f, col, str, length); +} + +int mailimf_fields_write_mem(MMAPString * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_fields_write_driver(do_write, f, col, fields); +} + +int mailimf_envelope_fields_write_mem(MMAPString * f, int * col, + struct mailimf_fields * fields) +{ + return mailimf_envelope_fields_write_driver(do_write, f, col, fields); +} + +int mailimf_field_write_mem(MMAPString * f, int * col, + struct mailimf_field * field) +{ + return mailimf_field_write_driver(do_write, f, col, field); +} + +int mailimf_quoted_string_write_mem(MMAPString * f, int * col, + const char * string, size_t len) +{ + return mailimf_quoted_string_write_driver(do_write, f, col, string, len); +} + +int mailimf_address_list_write_mem(MMAPString * f, int * col, + struct mailimf_address_list * addr_list) +{ + return mailimf_address_list_write_driver(do_write, f, col, addr_list); +} + +int mailimf_mailbox_list_write_mem(MMAPString * f, int * col, + struct mailimf_mailbox_list * mb_list) +{ + return mailimf_mailbox_list_write_driver(do_write, f, col, mb_list); +} + +int mailimf_header_string_write_mem(MMAPString * f, int * col, + const char * str, size_t length) +{ + return mailimf_header_string_write_driver(do_write, f, col, str, length); +} + Added: freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_mem.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/imf/mailimf_write_mem.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,135 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailimf_write_mem.h,v 1.2 2004/11/21 21:53:37 hoa Exp $ + */ + +#ifndef MAILIMF_WRITE_MEM_H + +#define MAILIMF_WRITE_MEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> +#include <libetpan/mailimf_types.h> +#include <libetpan/mmapstring.h> + +/* + mailimf_string_write_mem appends a string to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_string_write_mem(MMAPString * f, int * col, + const char * str, size_t length); + + +/* + mailimf_fields_write_mem appends the fields to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_fields_write_mem(MMAPString * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_envelope_fields_write_mem appends some fields to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param fields is the fields to write +*/ + +int mailimf_envelope_fields_write_mem(MMAPString * f, int * col, + struct mailimf_fields * fields); + + +/* + mailimf_field_write_mem appends a field to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param field is the field to write +*/ + +int mailimf_field_write_mem(MMAPString * f, int * col, + struct mailimf_field * field); + +/* + mailimf_quoted_string_write_mem appends a string that is quoted + to a given string + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param string is the string to quote and write +*/ + +int mailimf_quoted_string_write_mem(MMAPString * f, int * col, + const char * string, size_t len); + +int mailimf_address_list_write_mem(MMAPString * f, int * col, + struct mailimf_address_list * addr_list); + +int mailimf_mailbox_list_write_mem(MMAPString * f, int * col, + struct mailimf_mailbox_list * mb_list); + +/* + mailimf_header_string_write_mem appends a header value and fold the header + if needed. + + @param f is the string + @param col (* col) is the column number where we will start to + write the text, the ending column will be stored in (* col) + @param str is the string to write +*/ + +int mailimf_header_string_write_mem(MMAPString * f, int * col, + const char * str, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/maildir/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/maildir/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/low-level/maildir/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/maildir/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,8 @@ +top_builddir = ../../.. + +HEADERS = maildir.h maildir_types.h +SOURCES = maildir.c +TARGET = libmaildir +INCLUDES = -I$(srcdir)/data-types + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/low-level/maildir/maildir.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/maildir/maildir.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,811 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildir.c,v 1.17 2006/10/12 08:00:21 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "maildir.h" + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#ifdef _MSC_VER +# include "win_etpan.h" +#else +# include <unistd.h> +# include <sys/mman.h> +# include <dirent.h> +#endif +#include <sys/types.h> +#include <time.h> +#include <sys/stat.h> +#include <errno.h> +#include <fcntl.h> + +#ifdef LIBETPAN_SYSTEM_BASENAME +#include <libgen.h> +#endif + +/* + We suppose the maildir mailbox remains on one unique filesystem. +*/ + +struct maildir * maildir_new(const char * path) +{ + struct maildir * md; + + md = malloc(sizeof(* md)); + if (md == NULL) + goto err; + + md->mdir_counter = 0; + md->mdir_mtime_new = (time_t) -1; + md->mdir_mtime_cur = (time_t) -1; + + md->mdir_pid = getpid(); + gethostname(md->mdir_hostname, sizeof(md->mdir_hostname)); + strncpy(md->mdir_path, path, sizeof(md->mdir_path)); + md->mdir_path[PATH_MAX - 1] = '\0'; + + md->mdir_msg_list = carray_new(128); + if (md->mdir_msg_list == NULL) + goto free; + + md->mdir_msg_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE); + if (md->mdir_msg_hash == NULL) + goto free_msg_list; + + return md; + + free_msg_list: + carray_free(md->mdir_msg_list); + free: + free(md); + err: + return NULL; +} + +static void maildir_flush(struct maildir * md, int msg_new); +static void msg_free(struct maildir_msg * msg); + +void maildir_free(struct maildir * md) +{ + maildir_flush(md, 0); + maildir_flush(md, 1); + chash_free(md->mdir_msg_hash); + carray_free(md->mdir_msg_list); + free(md); +} + +#define MAX_TRY_ALLOC 32 + +static char * maildir_get_new_message_filename(struct maildir * md, + char * tmpfile) +{ + char filename[PATH_MAX]; + char basename[PATH_MAX]; + int k; + time_t now; + int got_file; + int r; + + got_file = 0; + now = time(NULL); + k = 0; + while (k < MAX_TRY_ALLOC) { + snprintf(basename, sizeof(basename), "%lu.%u_%u.%s", + (unsigned long) now, md->mdir_pid, md->mdir_counter, md->mdir_hostname); + snprintf(filename, sizeof(filename), "%s/tmp/%s", + md->mdir_path, basename); + + if (link(tmpfile, filename) == 0) { + got_file = 1; + unlink(tmpfile); + } + else if (errno == EXDEV) { + unlink(tmpfile); + return NULL; + } + else if (errno == EPERM) { + r = rename(tmpfile, filename); + if (r < 0) { + unlink(tmpfile); + return NULL; + } + got_file = 1; + } + + if (got_file) { + char * dup_filename; + + dup_filename = strdup(filename); + if (dup_filename == NULL) { + unlink(filename); + return NULL; + } + + md->mdir_counter ++; + + return dup_filename; + } + + md->mdir_counter ++; + k ++; + } + + return NULL; +} + + +static void msg_free(struct maildir_msg * msg) +{ + free(msg->msg_uid); + free(msg->msg_filename); + free(msg); +} + +/* + msg_new() + + filename is given without path +*/ + +static struct maildir_msg * msg_new(char * filename, int new_msg) +{ + struct maildir_msg * msg; + char * p; + int flags; + size_t uid_len; + char * begin_uid; + + /* name of file : xxx-xxx_xxx-xxx:2,SRFT */ + + msg = malloc(sizeof(* msg)); + if (msg == NULL) + goto err; + + msg->msg_filename = strdup(filename); + if (msg->msg_filename == NULL) + goto free; + + begin_uid = filename; + + uid_len = strlen(begin_uid); + + flags = 0; + p = strstr(filename, ":2,"); + if (p != NULL) { + uid_len = p - begin_uid; + + p += 3; + + /* parse flags */ + while (* p != '\0') { + switch (* p) { + case 'S': + flags |= MAILDIR_FLAG_SEEN; + break; + case 'R': + flags |= MAILDIR_FLAG_REPLIED; + break; + case 'F': + flags |= MAILDIR_FLAG_FLAGGED; + break; + case 'T': + flags |= MAILDIR_FLAG_TRASHED; + break; + } + p ++; + } + } + + if (new_msg) + flags |= MAILDIR_FLAG_NEW; + + msg->msg_flags = flags; + + msg->msg_uid = malloc(uid_len + 1); + if (msg->msg_uid == NULL) + goto free_filename; + + strncpy(msg->msg_uid, begin_uid, uid_len); + msg->msg_uid[uid_len] = '\0'; + + return msg; + + free_filename: + free(msg->msg_filename); + free: + free(msg); + err: + return NULL; +} + +static void maildir_flush(struct maildir * md, int msg_new) +{ + unsigned int i; + + i = 0; + while (i < carray_count(md->mdir_msg_list)) { + struct maildir_msg * msg; + int delete; + + msg = carray_get(md->mdir_msg_list, i); + + if (msg_new) { + delete = 0; + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + delete = 1; + } + else { + delete = 1; + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + delete = 0; + } + + if (delete) { + chashdatum key; + + key.data = msg->msg_uid; + key.len = strlen(msg->msg_uid); + chash_delete(md->mdir_msg_hash, &key, NULL); + + carray_delete(md->mdir_msg_list, i); + msg_free(msg); + } + else { + i ++; + } + } +} + +static int add_message(struct maildir * md, + char * filename, int is_new) +{ + struct maildir_msg * msg; + chashdatum key; + chashdatum value; + unsigned int i; + int res; + int r; + + msg = msg_new(filename, is_new); + if (msg == NULL) { + res = MAILDIR_ERROR_MEMORY; + goto err; + } + + r = carray_add(md->mdir_msg_list, msg, &i); + if (r < 0) { + res = MAILDIR_ERROR_MEMORY; + goto free_msg; + } + + key.data = msg->msg_uid; + key.len = strlen(msg->msg_uid); + value.data = msg; + value.len = 0; + + r = chash_set(md->mdir_msg_hash, &key, &value, NULL); + if (r < 0) { + res = MAILDIR_ERROR_MEMORY; + goto delete; + } + + return MAILDIR_NO_ERROR; + + delete: + carray_delete(md->mdir_msg_list, i); + free_msg: + msg_free(msg); + err: + return res; +} + +static int add_directory(struct maildir * md, char * path, int is_new) +{ + DIR * d; + struct dirent * entry; + int res; + int r; +#if 0 + char filename[PATH_MAX]; +#endif + + d = opendir(path); + if (d == NULL) { + res = MAILDIR_ERROR_DIRECTORY; + goto err; + } + + while ((entry = readdir(d)) != NULL) { +#if 0 + struct stat stat_info; + + snprintf(filename, sizeof(filename), "%s/%s", path, entry->d_name); + + r = stat(filename, &stat_info); + if (r < 0) + continue; + + if (S_ISDIR(stat_info.st_mode)) + continue; +#endif + + if (entry->d_name[0] == '.') + continue; + + r = add_message(md, entry->d_name, is_new); + if (r != MAILDIR_NO_ERROR) { + /* ignore errors */ + } + } + + closedir(d); + + return MAILDIR_NO_ERROR; + + err: + return res; +} + +int maildir_update(struct maildir * md) +{ + struct stat stat_info; + char path_new[PATH_MAX]; + char path_cur[PATH_MAX]; + char path_maildirfolder[PATH_MAX]; + int r; + int res; + int changed; + + snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path); + snprintf(path_cur, sizeof(path_cur), "%s/cur", md->mdir_path); + + changed = 0; + + /* did new/ changed ? */ + + r = stat(path_new, &stat_info); + if (r < 0) { + res = MAILDIR_ERROR_DIRECTORY; + goto free; + } + + if (md->mdir_mtime_new != stat_info.st_mtime) { + md->mdir_mtime_new = stat_info.st_mtime; + changed = 1; + } + + /* did cur/ changed ? */ + + r = stat(path_cur, &stat_info); + if (r < 0) { + res = MAILDIR_ERROR_DIRECTORY; + goto free; + } + + if (md->mdir_mtime_cur != stat_info.st_mtime) { + md->mdir_mtime_cur = stat_info.st_mtime; + changed = 1; + } + + if (changed) { + maildir_flush(md, 0); + maildir_flush(md, 1); + + /* messages in new */ + r = add_directory(md, path_new, 1); + if (r != MAILDIR_NO_ERROR) { + res = r; + goto free; + } + + /* messages in cur */ + r = add_directory(md, path_cur, 0); + if (r != MAILDIR_NO_ERROR) { + res = r; + goto free; + } + } + + snprintf(path_maildirfolder, sizeof(path_maildirfolder), + "%s/maildirfolder", md->mdir_path); + + if (stat(path_maildirfolder, &stat_info) == -1) { + int fd; + + fd = creat(path_maildirfolder, S_IRUSR | S_IWUSR); + if (fd != -1) + close(fd); + } + + return MAILDIR_NO_ERROR; + + free: + maildir_flush(md, 0); + maildir_flush(md, 1); + md->mdir_mtime_cur = (time_t) -1; + md->mdir_mtime_new = (time_t) -1; + return res; +} + +#ifndef LIBETPAN_SYSTEM_BASENAME +static char * libetpan_basename(char * filename) +{ + char * next; + char * p; + + p = filename; + next = strchr(p, '/'); + + while (next != NULL) { + p = next; + next = strchr(p + 1, '/'); + } + + if (p == filename) + return filename; + else + return p + 1; +} +#else +#define libetpan_basename(a) basename(a) +#endif + +int maildir_message_add_uid(struct maildir * md, + const char * message, size_t size, + char * uid, size_t max_uid_len) +{ + char path_new[PATH_MAX]; + char tmpname[PATH_MAX]; + int fd; + int r; + char * mapping; + char * delivery_tmp_name; + char * delivery_tmp_basename; + char delivery_new_name[PATH_MAX]; + char * delivery_new_basename; + int res; + struct stat stat_info; + + r = maildir_update(md); + if (r != MAILDIR_NO_ERROR) { + res = r; + goto err; + } + + /* write to tmp/ with a classic temporary file */ + + snprintf(tmpname, sizeof(tmpname), "%s/tmp/etpan-maildir-XXXXXX", + md->mdir_path); + fd = mkstemp(tmpname); + if (fd < 0) { + res = MAILDIR_ERROR_FILE; + goto err; + } + + r = ftruncate(fd, size); + if (r < 0) { + res = MAILDIR_ERROR_FILE; + goto close; + } + + mapping = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (mapping == (char *)MAP_FAILED) { + res = MAILDIR_ERROR_FILE; + goto close; + } + + memcpy(mapping, message, size); + + msync(mapping, size, MS_SYNC); + munmap(mapping, size); + + close(fd); + + /* write to tmp/ with maildir standard name */ + + delivery_tmp_name = maildir_get_new_message_filename(md, tmpname); + if (delivery_tmp_name == NULL) { + res = MAILDIR_ERROR_FILE; + goto unlink; + } + + /* write to new/ with maildir standard name */ + + strncpy(tmpname, delivery_tmp_name, sizeof(tmpname)); + tmpname[sizeof(tmpname) - 1] = '\0'; + + delivery_tmp_basename = libetpan_basename(tmpname); + + snprintf(delivery_new_name, sizeof(delivery_new_name), "%s/new/%s", + md->mdir_path, delivery_tmp_basename); + + r = link(delivery_tmp_name, delivery_new_name); + if (r == 0) { + unlink(delivery_tmp_name); + } + else if (errno == EXDEV) { + res = MAILDIR_ERROR_FOLDER; + goto unlink_tmp; + } + else if (errno == EPERM) { + r = rename(delivery_tmp_name, delivery_new_name); + if (r < 0) { + res = MAILDIR_ERROR_FILE; + goto unlink_tmp; + } + } + + snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path); + r = stat(path_new, &stat_info); + if (r < 0) { + unlink(delivery_new_name); + res = MAILDIR_ERROR_FILE; + goto unlink_tmp; + } + + md->mdir_mtime_new = stat_info.st_mtime; + + delivery_new_basename = libetpan_basename(delivery_new_name); + + r = add_message(md, delivery_new_basename, 1); + if (r != MAILDIR_NO_ERROR) { + unlink(delivery_new_name); + res = MAILDIR_ERROR_FILE; + goto unlink_tmp; + } + + if (uid != NULL) + strncpy(uid, delivery_new_basename, max_uid_len); + + free(delivery_tmp_name); + + return MAILDIR_NO_ERROR; + + unlink_tmp: + unlink(delivery_tmp_name); + free(delivery_tmp_name); + goto err; + close: + close(fd); + unlink: + unlink(tmpname); + err: + return res; +} + +int maildir_message_add(struct maildir * md, + const char * message, size_t size) +{ + return maildir_message_add_uid(md, message, size, + NULL, 0); +} + +int maildir_message_add_file_uid(struct maildir * md, int fd, + char * uid, size_t max_uid_len) +{ + char * message; + struct stat buf; + int r; + + if (fstat(fd, &buf) == -1) + return MAILDIR_ERROR_FILE; + + message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (message == (char *)MAP_FAILED) + return MAILDIR_ERROR_FILE; + + r = maildir_message_add_uid(md, message, buf.st_size, uid, max_uid_len); + + munmap(message, buf.st_size); + + return r; +} + +int maildir_message_add_file(struct maildir * md, int fd) +{ + return maildir_message_add_file_uid(md, fd, + NULL, 0); +} + +char * maildir_message_get(struct maildir * md, const char * uid) +{ + chashdatum key; + chashdatum value; + char filename[PATH_MAX]; + char * dup_filename; + struct maildir_msg * msg; + char * dir; + int r; + + key.data = (void *) uid; + key.len = strlen(uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) + return NULL; + + msg = value.data; + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + dir = "new"; + else + dir = "cur"; + + snprintf(filename, sizeof(filename), "%s/%s/%s", + md->mdir_path, dir, msg->msg_filename); + + dup_filename = strdup(filename); + if (dup_filename == NULL) + return NULL; + + return dup_filename; +} + +int maildir_message_remove(struct maildir * md, const char * uid) +{ + chashdatum key; + chashdatum value; + char filename[PATH_MAX]; + struct maildir_msg * msg; + char * dir; + int r; + int res; + + key.data = (void *) uid; + key.len = strlen(uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) { + res = MAILDIR_ERROR_NOT_FOUND; + goto err; + } + + msg = value.data; + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + dir = "new"; + else + dir = "cur"; + + snprintf(filename, sizeof(filename), "%s/%s/%s", + md->mdir_path, dir, msg->msg_filename); + + r = unlink(filename); + if (r < 0) { + res = MAILDIR_ERROR_FILE; + goto err; + } + + return MAILDIR_NO_ERROR; + + err: + return res; +} + +int maildir_message_change_flags(struct maildir * md, + const char * uid, int new_flags) +{ + chashdatum key; + chashdatum value; + char filename[PATH_MAX]; + struct maildir_msg * msg; + char * dir; + int r; + char new_filename[PATH_MAX]; + char flag_str[5]; + size_t i; + int res; + char * dup_filename; + + key.data = (void *) uid; + key.len = strlen(uid); + r = chash_get(md->mdir_msg_hash, &key, &value); + if (r < 0) { + res = MAILDIR_ERROR_NOT_FOUND; + goto err; + } + + msg = value.data; + if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) + dir = "new"; + else + dir = "cur"; + + snprintf(filename, sizeof(filename), "%s/%s/%s", + md->mdir_path, dir, msg->msg_filename); + + if ((new_flags & MAILDIR_FLAG_NEW) != 0) + dir = "new"; + else + dir = "cur"; + + i = 0; + if ((new_flags & MAILDIR_FLAG_SEEN) != 0) { + flag_str[i] = 'S'; + i ++; + } + if ((new_flags & MAILDIR_FLAG_REPLIED) != 0) { + flag_str[i] = 'R'; + i ++; + } + if ((new_flags & MAILDIR_FLAG_FLAGGED) != 0) { + flag_str[i] = 'F'; + i ++; + } + if ((new_flags & MAILDIR_FLAG_TRASHED) != 0) { + flag_str[i] = 'T'; + i ++; + } + flag_str[i] = 0; + + if (flag_str[0] == '\0') + snprintf(new_filename, sizeof(new_filename), "%s/%s/%s", + md->mdir_path, dir, msg->msg_uid); + else + snprintf(new_filename, sizeof(new_filename), "%s/%s/%s:2,%s", + md->mdir_path, dir, msg->msg_uid, flag_str); + + if (strcmp(filename, new_filename) == 0) + return MAILDIR_NO_ERROR; + + r = link(filename, new_filename); + if (r == 0) { + unlink(filename); + } + else if (errno == EXDEV) { + res = MAILDIR_ERROR_FOLDER; + goto err; + } + else if (errno == EPERM) { + r = rename(filename, new_filename); + if (r < 0) { + res = MAILDIR_ERROR_FOLDER; + goto err; + } + } + + dup_filename = strdup(libetpan_basename(new_filename)); + if (dup_filename != NULL) { + free(msg->msg_filename); + msg->msg_filename = dup_filename; + } + + msg->msg_flags = new_flags; + + return MAILDIR_NO_ERROR; + + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/maildir/maildir.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/maildir/maildir.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,67 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildir.h,v 1.5 2004/11/21 21:53:38 hoa Exp $ + */ + +#ifndef MAILDIR_H + +#define MAILDIR_H + +#include <libetpan/maildir_types.h> + +struct maildir * maildir_new(const char * path); + +void maildir_free(struct maildir * md); + +int maildir_update(struct maildir * md); + +int maildir_message_add_uid(struct maildir * md, + const char * message, size_t size, + char * uid, size_t max_uid_len); + +int maildir_message_add(struct maildir * md, + const char * message, size_t size); + +int maildir_message_add_file_uid(struct maildir * md, int fd, + char * uid, size_t max_uid_len); + +int maildir_message_add_file(struct maildir * md, int fd); + +char * maildir_message_get(struct maildir * md, const char * uid); + +int maildir_message_remove(struct maildir * md, const char * uid); + +int maildir_message_change_flags(struct maildir * md, + const char * uid, int new_flags); + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/maildir/maildir_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/maildir/maildir_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,93 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: maildir_types.h,v 1.9 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILDIR_TYPES_H + +#define MAILDIR_TYPES_H + +#include <sys/types.h> +#include <libetpan/libetpan-config.h> +#include <libetpan/chash.h> +#include <libetpan/carray.h> +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif + +#include <libetpan/libetpan-config.h> + +#define LIBETPAN_MAILDIR + +enum { + MAILDIR_NO_ERROR = 0, + MAILDIR_ERROR_CREATE, + MAILDIR_ERROR_DIRECTORY, + MAILDIR_ERROR_MEMORY, + MAILDIR_ERROR_FILE, + MAILDIR_ERROR_NOT_FOUND, + MAILDIR_ERROR_FOLDER +}; + +#define MAILDIR_FLAG_NEW (1 << 0) +#define MAILDIR_FLAG_SEEN (1 << 1) +#define MAILDIR_FLAG_REPLIED (1 << 2) +#define MAILDIR_FLAG_FLAGGED (1 << 3) +#define MAILDIR_FLAG_TRASHED (1 << 4) + +struct maildir_msg { + char * msg_uid; + char * msg_filename; + int msg_flags; +}; + +/* + work around for missing #define HOST_NAME_MAX in Linux +*/ + +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 255 +#endif + +struct maildir { + pid_t mdir_pid; + char mdir_hostname[HOST_NAME_MAX]; + char mdir_path[PATH_MAX]; + uint32_t mdir_counter; + time_t mdir_mtime_new; + time_t mdir_mtime_cur; + carray * mdir_msg_list; + chash * mdir_msg_hash; +}; + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/mbox/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mbox/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/low-level/mbox/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mbox/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,8 @@ +top_builddir = ../../.. + +HEADERS = mailmbox.h mailmbox_types.h +SOURCES = mailmbox_parse.c mailmbox.c mailmbox_types.c +TARGET = libmbox +INCLUDES = -I$(srcdir)/data-types -I../imf + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/low-level/mbox/TODO ============================================================================== Added: freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1576 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmbox.c,v 1.44 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmbox.h" + +#ifdef _MSC_VER +# include "win_etpan.h" +#else +# include <sys/file.h> +# include <unistd.h> +# include <sys/mman.h> +#endif +#include <sys/stat.h> +#include <fcntl.h> +#include <time.h> +#include <sys/types.h> + +#include <string.h> +#include <ctype.h> +#include <stdlib.h> +#include <stdio.h> + +#include "libetpan-config.h" + +#include "mmapstring.h" +#include "mailmbox_parse.h" +#include "maillock.h" + +#if 0 +#define CRLF_BADNESS +#endif + +/* + http://www.qmail.org/qmail-manual-html/man5/mbox.html + RFC 2076 +*/ + +/* used only in case the directory which contains the original file + is not writable */ +#define TMPDIR "/tmp" + +/* mbox is a file with a corresponding filename */ + +#define UID_HEADER "X-LibEtPan-UID:" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +int mailmbox_write_lock(struct mailmbox_folder * folder) +{ + int r; + + if (folder->mb_read_only) + return MAILMBOX_ERROR_READONLY; + + r = maillock_write_lock(folder->mb_filename, folder->mb_fd); + if (r == 0) + return MAILMBOX_NO_ERROR; + else + return MAILMBOX_ERROR_FILE; +} + +int mailmbox_write_unlock(struct mailmbox_folder * folder) +{ + int r; + + r = maillock_write_unlock(folder->mb_filename, folder->mb_fd); + if (r == 0) + return MAILMBOX_NO_ERROR; + else + return MAILMBOX_ERROR_FILE; +} + +int mailmbox_read_lock(struct mailmbox_folder * folder) +{ + int r; + + r = maillock_read_lock(folder->mb_filename, folder->mb_fd); + if (r == 0) + return MAILMBOX_NO_ERROR; + else + return MAILMBOX_ERROR_FILE; +} + +int mailmbox_read_unlock(struct mailmbox_folder * folder) +{ + int r; + + r = maillock_read_unlock(folder->mb_filename, folder->mb_fd); + if (r == 0) + return MAILMBOX_NO_ERROR; + else + return MAILMBOX_ERROR_FILE; +} + + +/* + map the file into memory. + the file must be locked. +*/ + +int mailmbox_map(struct mailmbox_folder * folder) +{ + char * str; + struct stat buf; + int res; + int r; + + r = stat(folder->mb_filename, &buf); + if (r < 0) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + + if (folder->mb_read_only) + str = (char *) mmap(0, buf.st_size, PROT_READ, + MAP_PRIVATE, folder->mb_fd, 0); + else + str = (char *) mmap(0, buf.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, folder->mb_fd, 0); + if (str == (char *)MAP_FAILED) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + + folder->mb_mapping = str; + folder->mb_mapping_size = buf.st_size; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +/* + unmap the file +*/ + +void mailmbox_unmap(struct mailmbox_folder * folder) +{ + munmap(folder->mb_mapping, folder->mb_mapping_size); + folder->mb_mapping = NULL; + folder->mb_mapping_size = 0; +} + +void mailmbox_sync(struct mailmbox_folder * folder) +{ + msync(folder->mb_mapping, folder->mb_mapping_size, MS_SYNC); +} + +void mailmbox_timestamp(struct mailmbox_folder * folder) +{ + int r; + struct stat buf; + + r = stat(folder->mb_filename, &buf); + if (r < 0) + folder->mb_mtime = (time_t) -1; + else + folder->mb_mtime = buf.st_mtime; +} + +/* + open the file +*/ + +int mailmbox_open(struct mailmbox_folder * folder) +{ + int fd; + int read_only; + + fd = -1; + read_only = TRUE; + + if (!folder->mb_read_only) { + read_only = FALSE; + fd = open(folder->mb_filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + } + + if (folder->mb_read_only || (fd < 0)) { + read_only = TRUE; + fd = open(folder->mb_filename, O_RDONLY); + if (fd < 0) + return MAILMBOX_ERROR_FILE_NOT_FOUND; + } + + folder->mb_fd = fd; + folder->mb_read_only = read_only; + + return MAILMBOX_NO_ERROR; +} + +/* + close the file +*/ + +void mailmbox_close(struct mailmbox_folder * folder) +{ + close(folder->mb_fd); + folder->mb_fd = -1; +} + + +static int mailmbox_validate_lock(struct mailmbox_folder * folder, + int (* custom_lock)(struct mailmbox_folder *), + int (* custom_unlock)(struct mailmbox_folder *)) +{ + struct stat buf; + int res; + int r; + + r = stat(folder->mb_filename, &buf); + if (r < 0) { + buf.st_mtime = (time_t) -1; + } + + if ((buf.st_mtime != folder->mb_mtime) || + ((size_t) buf.st_size != folder->mb_mapping_size)) { + int r; + + mailmbox_unmap(folder); + mailmbox_close(folder); + + r = mailmbox_open(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = custom_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_map(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err_unlock; + } + + r = mailmbox_parse(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err_unlock; + } + + folder->mb_mtime = buf.st_mtime; + + return MAILMBOX_NO_ERROR; + } + else { + r = custom_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + } + + return MAILMBOX_NO_ERROR; + + err_unlock: + custom_unlock(folder); + err: + return res; +} + + +int mailmbox_validate_write_lock(struct mailmbox_folder * folder) +{ + return mailmbox_validate_lock(folder, + mailmbox_write_lock, + mailmbox_write_unlock); +} + + +int mailmbox_validate_read_lock(struct mailmbox_folder * folder) +{ + return mailmbox_validate_lock(folder, + mailmbox_read_lock, + mailmbox_read_unlock); +} + + +/* ********************************************************************** */ +/* append messages */ + +#define MAX_FROM_LINE_SIZE 256 + +static inline size_t get_line(const char * line, size_t length, + const char ** pnext_line, size_t * pcount) +{ + size_t count; + + count = 0; + + while (1) { + if (length == 0) + break; + + if (* line == '\r') { + line ++; + + count ++; + length --; + + if (length > 0) { + if (* line == '\n') { + line ++; + + count ++; + length --; + + break; + } + } + } + else if (* line == '\n') { + line ++; + + count ++; + length --; + + break; + } + else { + line ++; + length --; + count ++; + } + } + + * pnext_line = line; + * pcount = count; + + return count; +} + +/* + TODO : should strip \r\n if any + see also in write_fixed_line +*/ + +static inline size_t get_fixed_line_size(const char * line, size_t length, + const char ** pnext_line, size_t * pcount, + size_t * pfixed_count) +{ + size_t count; + const char * next_line; + size_t fixed_count; + + if (!get_line(line, length, &next_line, &count)) + return 0; + + fixed_count = count; + if (count >= 5) { + if (line[0] == 'F') { + if (strncmp(line, "From ", 5) == 0) + fixed_count ++; + } + } + + * pnext_line = next_line; + * pcount = count; + * pfixed_count = fixed_count; + + return count; +} + +static size_t get_fixed_message_size(const char * message, size_t size, + uint32_t uid, int force_no_uid) +{ + size_t fixed_size; + size_t cur_token; + size_t left; + const char * next; + const char * cur; + int end; + int r; + uint32_t tmp_uid; + + cur_token = 0; + + fixed_size = 0; + + /* headers */ + + end = FALSE; + while (!end) { + size_t begin; + int ignore; + + ignore = FALSE; + begin = cur_token; + if (cur_token + strlen(UID_HEADER) <= size) { + if (message[cur_token] == 'X') { + if (strncasecmp(message + cur_token, UID_HEADER, + strlen(UID_HEADER)) == 0) { + ignore = TRUE; + } + } + } + + r = mailimf_ignore_field_parse(message, size, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + if (!ignore) + fixed_size += cur_token - begin; + break; + case MAILIMF_ERROR_PARSE: + default: + end = TRUE; + break; + } + } + + if (!force_no_uid) { + /* UID header */ + +#ifdef CRLF_BADNESS + fixed_size += strlen(UID_HEADER " \r\n"); +#else + fixed_size += strlen(UID_HEADER " \n"); +#endif + + tmp_uid = uid; + while (tmp_uid >= 10) { + tmp_uid /= 10; + fixed_size ++; + } + fixed_size ++; + } + + /* body */ + + left = size - cur_token; + next = message + cur_token; + while (left > 0) { + size_t count; + size_t fixed_count; + + cur = next; + + if (!get_fixed_line_size(cur, left, &next, &count, &fixed_count)) + break; + + fixed_size += fixed_count; + left -= count; + } + + return fixed_size; +} + +static inline char * write_fixed_line(char * str, + const char * line, size_t length, + const char ** pnext_line, size_t * pcount) +{ + size_t count; + const char * next_line; + + if (!get_line(line, length, &next_line, &count)) + return str; + + if (count >= 5) { + if (line[0] == 'F') { + if (strncmp(line, "From ", 5) == 0) { + * str = '>'; + str ++; + } + } + } + + memcpy(str, line, count); + + * pnext_line = next_line; + * pcount = count; + str += count; + + return str; +} + +static char * write_fixed_message(char * str, + const char * message, size_t size, + uint32_t uid, int force_no_uid) +{ + size_t fixed_size; + size_t cur_token; + size_t left; + int end; + int r; + const char * cur_src; + size_t numlen; + + cur_token = 0; + + fixed_size = 0; + + /* headers */ + + end = FALSE; + while (!end) { + size_t begin; + int ignore; + + ignore = FALSE; + begin = cur_token; + if (cur_token + strlen(UID_HEADER) <= size) { + if (message[cur_token] == 'X') { + if (strncasecmp(message + cur_token, UID_HEADER, + strlen(UID_HEADER)) == 0) { + ignore = TRUE; + } + } + } + + r = mailimf_ignore_field_parse(message, size, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + if (!ignore) { + memcpy(str, message + begin, cur_token - begin); + str += cur_token - begin; + } + break; + case MAILIMF_ERROR_PARSE: + default: + end = TRUE; + break; + } + } + + if (!force_no_uid) { + /* UID header */ + + memcpy(str, UID_HEADER " ", strlen(UID_HEADER " ")); + str += strlen(UID_HEADER " "); +#ifdef CRLF_BADNESS + numlen = snprintf(str, 20, "%i\r\n", uid); +#else + numlen = snprintf(str, 20, "%i\n", uid); +#endif + str += numlen; + } + + /* body */ + + cur_src = message + cur_token; + left = size - cur_token; + while (left > 0) { + size_t count; + const char * next; + + count = 0; + next = NULL; + str = write_fixed_line(str, cur_src, left, &next, &count); + + cur_src = next; + left -= count; + } + + return str; +} + +#define DEFAULT_FROM_LINE "From - Wed Jun 30 21:49:08 1993\n" + +int +mailmbox_append_message_list_no_lock(struct mailmbox_folder * folder, + carray * append_tab) +{ + size_t extra_size; + int r; + char from_line[MAX_FROM_LINE_SIZE] = DEFAULT_FROM_LINE; + struct tm time_info; + time_t date; + int res; + size_t old_size; + char * str; + unsigned int i; + size_t from_size; + size_t maxuid; + size_t left; + size_t crlf_count; + + if (folder->mb_read_only) { + res = MAILMBOX_ERROR_READONLY; + goto err; + } + + date = time(NULL); + from_size = strlen(DEFAULT_FROM_LINE); + if (localtime_r(&date, &time_info) != NULL) +#ifdef CRLF_BADNESS + from_size = strftime(from_line, MAX_FROM_LINE_SIZE, "From - %c\r\n", &time_info); +#else + from_size = strftime(from_line, MAX_FROM_LINE_SIZE, "From - %c\n", &time_info); +#endif + + maxuid = /* */ folder->mb_max_uid; + + extra_size = 0; + for(i = 0 ; i < carray_count(append_tab) ; i ++) { + struct mailmbox_append_info * info; + + info = carray_get(append_tab, i); + extra_size += from_size; + extra_size += get_fixed_message_size(info->ai_message, info->ai_size, + folder->mb_max_uid + i + 1, + folder->mb_no_uid); +#ifdef CRLF_BADNESS + extra_size += 2; /* CR LF */ +#else + extra_size += 1; /* CR LF */ +#endif + + info->ai_uid = folder->mb_max_uid + i + 1; + } + + left = folder->mb_mapping_size; + crlf_count = 0; + while (left >= 1) { + if (folder->mb_mapping[left - 1] == '\n') { + crlf_count ++; + left --; + } +#ifdef CRLF_BADNESS + else if (folder->mb_mapping[left - 1] == '\r') { + left --; + } +#endif + else + break; + + if (crlf_count == 2) + break; + } + + old_size = folder->mb_mapping_size; + mailmbox_unmap(folder); + + if (old_size != 0) { + if (crlf_count != 2) +#ifdef CRLF_BADNESS + extra_size += (2 - crlf_count) * 2; +#else + /* Need the number of LFs, not CRLFs */ + extra_size += (2 - crlf_count) * 1; +#endif + } + + r = ftruncate(folder->mb_fd, extra_size + old_size); + if (r < 0) { + mailmbox_map(folder); + res = MAILMBOX_ERROR_FILE; + goto err; + } + + r = mailmbox_map(folder); + if (r < 0) { + ftruncate(folder->mb_fd, old_size); + return MAILMBOX_ERROR_FILE; + } + + str = folder->mb_mapping + old_size; + + if (old_size != 0) { + for(i = 0 ; i < 2 - crlf_count ; i ++) { +#ifdef CRLF_BADNESS + * str = '\r'; + str ++; +#endif + * str = '\n'; + str ++; + } + } + + for(i = 0 ; i < carray_count(append_tab) ; i ++) { + struct mailmbox_append_info * info; + + info = carray_get(append_tab, i); + + memcpy(str, from_line, from_size); + + str += strlen(from_line); + + str = write_fixed_message(str, info->ai_message, info->ai_size, + folder->mb_max_uid + i + 1, + folder->mb_no_uid); + +#ifdef CRLF_BADNESS + * str = '\r'; + str ++; +#endif + * str = '\n'; + str ++; + } + + folder->mb_max_uid += carray_count(append_tab); + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +int +mailmbox_append_message_list(struct mailmbox_folder * folder, + carray * append_tab) +{ + int r; + int res; + size_t cur_token; + + r = mailmbox_validate_write_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_expunge_no_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + cur_token = folder->mb_mapping_size; + + r = mailmbox_append_message_list_no_lock(folder, append_tab); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + mailmbox_sync(folder); + + r = mailmbox_parse_additionnal(folder, &cur_token); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + mailmbox_timestamp(folder); + + mailmbox_write_unlock(folder); + + return MAILMBOX_NO_ERROR; + + unlock: + mailmbox_write_unlock(folder); + err: + return res; +} + +int +mailmbox_append_message_uid(struct mailmbox_folder * folder, + const char * data, size_t len, unsigned int * puid) +{ + carray * tab; + struct mailmbox_append_info * append_info; + int res; + int r; + + tab = carray_new(1); + if (tab == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + + append_info = mailmbox_append_info_new(data, len); + if (append_info == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto free_list; + } + + r = carray_add(tab, append_info, NULL); + if (r < 0) { + res = MAILMBOX_ERROR_MEMORY; + goto free_append_info; + } + + r = mailmbox_append_message_list(folder, tab); + + if (puid != NULL) + * puid = append_info->ai_uid; + + mailmbox_append_info_free(append_info); + carray_free(tab); + + return r; + + free_append_info: + mailmbox_append_info_free(append_info); + free_list: + carray_free(tab); + err: + return res; +} + +int +mailmbox_append_message(struct mailmbox_folder * folder, + const char * data, size_t len) +{ + return mailmbox_append_message_uid(folder, data, len, NULL); +} + +/* ********************************************************************** */ + +int mailmbox_fetch_msg_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len) +{ + struct mailmbox_msg_info * info; + int res; + chashdatum key; + chashdatum data; + int r; + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + if (info->msg_deleted) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + * result = folder->mb_mapping + info->msg_headers; + * result_len = info->msg_size - info->msg_start_len; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +int mailmbox_fetch_msg_headers_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len) +{ + struct mailmbox_msg_info * info; + int res; + chashdatum key; + chashdatum data; + int r; + + key.data = # + key.len = sizeof(num); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + if (info->msg_deleted) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + * result = folder->mb_mapping + info->msg_headers; + * result_len = info->msg_headers_len; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +int mailmbox_fetch_msg(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + int res; + char * data; + size_t len; + int r; + size_t fixed_size; + char * end; + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_fetch_msg_no_lock(folder, num, &data, &len); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + + /* size with no uid */ + fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */); + +#if 0 + mmapstr = mmap_string_new_len(data, fixed_size); + if (mmapstr == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } +#endif + mmapstr = mmap_string_sized_new(fixed_size); + if (mmapstr == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } + + end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */); + * end = '\0'; + mmapstr->len = fixed_size; + + r = mmap_string_ref(mmapstr); + if (r < 0) { + mmap_string_free(mmapstr); + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + mailmbox_read_unlock(folder); + + return MAILMBOX_NO_ERROR; + + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + +int mailmbox_fetch_msg_headers(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + int res; + char * data; + size_t len; + int r; + size_t fixed_size; + char * end; + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_fetch_msg_headers_no_lock(folder, num, &data, &len); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlock; + } + +#if 0 + mmapstr = mmap_string_new_len(data, len); + if (mmapstr == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } +#endif + /* size with no uid */ + fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */); + + mmapstr = mmap_string_sized_new(fixed_size); + if (mmapstr == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } + + end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */); + * end = '\0'; + mmapstr->len = fixed_size; + + r = mmap_string_ref(mmapstr); + if (r < 0) { + mmap_string_free(mmapstr); + res = MAILMBOX_ERROR_MEMORY; + goto unlock; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + mailmbox_read_unlock(folder); + + return MAILMBOX_NO_ERROR; + + unlock: + mailmbox_read_unlock(folder); + err: + return res; +} + +void mailmbox_fetch_result_free(char * msg) +{ + mmap_string_unref(msg); +} + + +int mailmbox_copy_msg_list(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + carray * tab) +{ + int r; + int res; + carray * append_tab; + unsigned int i; + + r = mailmbox_validate_read_lock(src_folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + append_tab = carray_new(carray_count(tab)); + if (append_tab == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto src_unlock; + } + + for(i = 0 ; i < carray_count(tab) ; i ++) { + struct mailmbox_append_info * append_info; + char * data; + size_t len; + uint32_t uid; + + uid = * ((uint32_t *) carray_get(tab, i)); + + r = mailmbox_fetch_msg_no_lock(src_folder, uid, &data, &len); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto free_list; + } + + append_info = mailmbox_append_info_new(data, len); + if (append_info == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto free_list; + } + + r = carray_add(append_tab, append_info, NULL); + if (r < 0) { + mailmbox_append_info_free(append_info); + res = MAILMBOX_ERROR_MEMORY; + goto free_list; + } + } + + r = mailmbox_append_message_list(dest_folder, append_tab); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto src_unlock; + } + + for(i = 0 ; i < carray_count(append_tab) ; i ++) { + struct mailmbox_append_info * append_info; + + append_info = carray_get(append_tab, i); + mailmbox_append_info_free(append_info); + } + carray_free(append_tab); + + mailmbox_read_unlock(src_folder); + + return MAILMBOX_NO_ERROR; + + free_list: + for(i = 0 ; i < carray_count(append_tab) ; i ++) { + struct mailmbox_append_info * append_info; + + append_info = carray_get(append_tab, i); + mailmbox_append_info_free(append_info); + } + carray_free(append_tab); + src_unlock: + mailmbox_read_unlock(src_folder); + err: + return res; +} + +int mailmbox_copy_msg(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + uint32_t uid) +{ + carray * tab; + int res; + uint32_t * puid; + int r; + + tab = carray_new(1); + if (tab == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + + puid = malloc(sizeof(* puid)); + if (puid == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto free_array; + } + * puid = uid; + + r = mailmbox_copy_msg_list(dest_folder, src_folder, tab); + res = r; + + free(puid); + free_array: + carray_free(tab); + err: + return res; +} + +static int mailmbox_expunge_to_file_no_lock(char * dest_filename, int dest_fd, + struct mailmbox_folder * folder, + size_t * result_size) +{ + int r; + int res; + unsigned long i; + size_t cur_offset; + char * dest; + size_t size; + + size = 0; + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + + if (!info->msg_deleted) { + size += info->msg_size + info->msg_padding; + + if (!folder->mb_no_uid) { + if (!info->msg_written_uid) { + uint32_t uid; + +#ifdef CRLF_BADNESS + size += strlen(UID_HEADER " \r\n"); +#else + size += strlen(UID_HEADER " \n"); +#endif + + uid = info->msg_uid; + while (uid >= 10) { + uid /= 10; + size ++; + } + size ++; + } + } + } + } + + r = ftruncate(dest_fd, size); + if (r < 0) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + + dest = (char *) mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, dest_fd, 0); + if (dest == (char *)MAP_FAILED) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + + cur_offset = 0; + for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + + if (!info->msg_deleted) { + memcpy(dest + cur_offset, folder->mb_mapping + info->msg_start, + info->msg_headers_len + info->msg_start_len); + cur_offset += info->msg_headers_len + info->msg_start_len; + + if (!folder->mb_no_uid) { + if (!info->msg_written_uid) { + size_t numlen; + + memcpy(dest + cur_offset, UID_HEADER " ", strlen(UID_HEADER " ")); + cur_offset += strlen(UID_HEADER " "); +#ifdef CRLF_BADNESS + numlen = snprintf(dest + cur_offset, size - cur_offset, + "%i\r\n", info->msg_uid); +#else + numlen = snprintf(dest + cur_offset, size - cur_offset, + "%i\n", info->msg_uid); +#endif + cur_offset += numlen; + } + } + + memcpy(dest + cur_offset, + folder->mb_mapping + info->msg_headers + info->msg_headers_len, + info->msg_size - (info->msg_start_len + info->msg_headers_len) + + info->msg_padding); + + cur_offset += info->msg_size - + (info->msg_start_len + info->msg_headers_len) + + info->msg_padding; + } + } + fflush(stdout); + + msync(dest, size, MS_SYNC); + munmap(dest, size); + + * result_size = size; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +static int copy_to_old_file(char * source_filename, + char * destination_filename, size_t size) +{ + int source_fd; + int dest_fd; + char * source; + char * dest; + int res; + int r; + + source_fd = open(source_filename, O_RDONLY); + if (source_fd < 0) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + + source = (char *) mmap(0, size, PROT_READ, MAP_PRIVATE, source_fd, 0); + if (source == (char *)MAP_FAILED) { + res = MAILMBOX_ERROR_FILE; + goto close_source; + } + + dest_fd = open(destination_filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (dest_fd < 0) { + res = MAILMBOX_ERROR_FILE; + goto unmap_source; + } + + r = ftruncate(dest_fd, size); + if (r < 0) { + res = MAILMBOX_ERROR_FILE; + goto close_dest; + } + + dest = (char *) mmap(0, size, PROT_READ | PROT_WRITE, + MAP_SHARED, dest_fd, 0); + if (dest == (char *)MAP_FAILED) { + res = MAILMBOX_ERROR_FILE; + goto close_dest; + } + + memcpy(dest, source, size); + + munmap(dest, size); + close(source_fd); + munmap(source, size); + close(source_fd); + + return MAILMBOX_NO_ERROR; + + unmap_dest: + munmap(dest, size); + close_dest: + close(source_fd); + unmap_source: + munmap(source, size); + close_source: + close(source_fd); + err: + return res; +} + +int mailmbox_expunge_no_lock(struct mailmbox_folder * folder) +{ + char tmpfile[PATH_MAX]; + int r; + int res; + int dest_fd; + size_t size; + mode_t old_mask; + + if (folder->mb_read_only) + return MAILMBOX_ERROR_READONLY; + + if (((folder->mb_written_uid >= folder->mb_max_uid) || folder->mb_no_uid) && + (!folder->mb_changed)) { + /* no need to expunge */ + return MAILMBOX_NO_ERROR; + } + + snprintf(tmpfile, PATH_MAX, "%sXXXXXX", folder->mb_filename); + old_mask = umask(0077); + dest_fd = mkstemp(tmpfile); + umask(old_mask); + + if (dest_fd < 0) { + /* fallback to tmp dir */ + + snprintf(tmpfile, PATH_MAX, TMPDIR "/etpan-unsafe-XXXXXX"); + + old_mask = umask(0077); + dest_fd = mkstemp(tmpfile); + umask(old_mask); + + if (dest_fd < 0) { + res = MAILMBOX_ERROR_FILE; + goto err; + } + } + + r = mailmbox_expunge_to_file_no_lock(tmpfile, dest_fd, + folder, &size); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unlink; + } + + close(dest_fd); + + r = rename(tmpfile, folder->mb_filename); + if (r < 0) { + mailmbox_unmap(folder); + mailmbox_close(folder); + + /* fallback on copy to old file */ + + r = copy_to_old_file(tmpfile, folder->mb_filename, size); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + unlink(tmpfile); + } + else { + mailmbox_unmap(folder); + mailmbox_close(folder); + } + + r = mailmbox_open(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_map(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_parse(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + mailmbox_timestamp(folder); + + folder->mb_changed = FALSE; + folder->mb_deleted_count = 0; + + return MAILMBOX_NO_ERROR; + + unlink: + close(dest_fd); + unlink(tmpfile); + err: + return res; +} + +int mailmbox_expunge(struct mailmbox_folder * folder) +{ + int r; + int res; + + r = mailmbox_validate_write_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + r = mailmbox_expunge_no_lock(folder); + res = r; + + mailmbox_write_unlock(folder); + err: + return res; +} + +int mailmbox_delete_msg(struct mailmbox_folder * folder, uint32_t uid) +{ + struct mailmbox_msg_info * info; + int res; + chashdatum key; + chashdatum data; + int r; + + if (folder->mb_read_only) { + res = MAILMBOX_ERROR_READONLY; + goto err; + } + + key.data = &uid; + key.len = sizeof(uid); + + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + info = data.data; + + if (info->msg_deleted) { + res = MAILMBOX_ERROR_MSG_NOT_FOUND; + goto err; + } + + info->msg_deleted = TRUE; + folder->mb_changed = TRUE; + folder->mb_deleted_count ++; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + + +/* + INIT of MBOX + + - open file + - map the file + + - lock the file + + - parse memory + + - unlock the file +*/ + +int mailmbox_init(const char * filename, + int force_readonly, + int force_no_uid, + uint32_t default_written_uid, + struct mailmbox_folder ** result_folder) +{ + struct mailmbox_folder * folder; + int r; + int res; + + folder = mailmbox_folder_new(filename); + if (folder == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + folder->mb_no_uid = force_no_uid; + folder->mb_read_only = force_readonly; + folder->mb_written_uid = default_written_uid; + + folder->mb_changed = FALSE; + folder->mb_deleted_count = 0; + + r = mailmbox_open(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto free; + } + + r = mailmbox_map(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto close; + } + + r = mailmbox_validate_read_lock(folder); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto unmap; + } + + mailmbox_read_unlock(folder); + + * result_folder = folder; + + return MAILMBOX_NO_ERROR; + + unmap: + mailmbox_unmap(folder); + close: + mailmbox_close(folder); + free: + mailmbox_folder_free(folder); + err: + return res; +} + + +/* + when MBOX is DONE + + - check for changes + + - unmap the file + - close file +*/ + +void mailmbox_done(struct mailmbox_folder * folder) +{ + if (!folder->mb_read_only) + mailmbox_expunge(folder); + + mailmbox_unmap(folder); + mailmbox_close(folder); + + mailmbox_folder_free(folder); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,144 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmbox.h,v 1.19 2004/11/21 21:53:38 hoa Exp $ + */ + +#ifndef MAILMBOX_H + +#define MAILMBOX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailmbox_types.h> + +int +mailmbox_append_message_list(struct mailmbox_folder * folder, + carray * append_tab); + +int +mailmbox_append_message(struct mailmbox_folder * folder, + const char * data, size_t len); + +int +mailmbox_append_message_uid(struct mailmbox_folder * folder, + const char * data, size_t len, unsigned int * puid); + +int mailmbox_fetch_msg(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +int mailmbox_fetch_msg_headers(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +void mailmbox_fetch_result_free(char * msg); + +int mailmbox_copy_msg_list(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + carray * tab); + +int mailmbox_copy_msg(struct mailmbox_folder * dest_folder, + struct mailmbox_folder * src_folder, + uint32_t uid); + +int mailmbox_expunge(struct mailmbox_folder * folder); + +int mailmbox_delete_msg(struct mailmbox_folder * folder, uint32_t uid); + +int mailmbox_init(const char * filename, + int force_readonly, + int force_no_uid, + uint32_t default_written_uid, + struct mailmbox_folder ** result_folder); + +void mailmbox_done(struct mailmbox_folder * folder); + +/* low-level access primitives */ + +int mailmbox_write_lock(struct mailmbox_folder * folder); + +int mailmbox_write_unlock(struct mailmbox_folder * folder); + +int mailmbox_read_lock(struct mailmbox_folder * folder); + +int mailmbox_read_unlock(struct mailmbox_folder * folder); + + +/* memory map */ + +int mailmbox_map(struct mailmbox_folder * folder); + +void mailmbox_unmap(struct mailmbox_folder * folder); + +void mailmbox_sync(struct mailmbox_folder * folder); + + +/* open & close file */ + +int mailmbox_open(struct mailmbox_folder * folder); + +void mailmbox_close(struct mailmbox_folder * folder); + + +/* validate cache */ + +int mailmbox_validate_write_lock(struct mailmbox_folder * folder); + +int mailmbox_validate_read_lock(struct mailmbox_folder * folder); + + +/* fetch message */ + +int mailmbox_fetch_msg_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +int mailmbox_fetch_msg_headers_no_lock(struct mailmbox_folder * folder, + uint32_t num, char ** result, + size_t * result_len); + +/* append message */ + +int +mailmbox_append_message_list_no_lock(struct mailmbox_folder * folder, + carray * append_tab); + +int mailmbox_expunge_no_lock(struct mailmbox_folder * folder); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox_parse.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox_parse.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,624 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmbox_parse.c,v 1.15 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmbox_parse.h" + +#include "mailmbox.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <stdlib.h> + +#define UID_HEADER "X-LibEtPan-UID:" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +enum { + UNSTRUCTURED_START, + UNSTRUCTURED_CR, + UNSTRUCTURED_LF, + UNSTRUCTURED_WSP, + UNSTRUCTURED_OUT +}; + +static inline int +mailmbox_fields_parse(char * str, size_t length, + size_t * index, + uint32_t * puid, + size_t * phlen) +{ + size_t cur_token; + int r; + size_t hlen; + size_t uid; + int end; + + cur_token = * index; + + end = FALSE; + uid = 0; + while (!end) { + size_t begin; + + begin = cur_token; + + r = mailimf_ignore_field_parse(str, length, &cur_token); + switch (r) { + case MAILIMF_NO_ERROR: + if (str[begin] == 'X') { + + if (strncasecmp(str + begin, UID_HEADER, strlen(UID_HEADER)) == 0) { + begin += strlen(UID_HEADER); + + while (str[begin] == ' ') + begin ++; + + uid = strtoul(str + begin, NULL, 10); + } + } + + break; + case MAILIMF_ERROR_PARSE: + default: + end = TRUE; + break; + } + } + + hlen = cur_token - * index; + + * phlen = hlen; + * puid = uid; + * index = cur_token; + + return MAILMBOX_NO_ERROR; +} + +enum { + IN_MAIL, + FIRST_CR, + FIRST_LF, + SECOND_CR, + SECOND_LF, + PARSING_F, + PARSING_R, + PARSING_O, + PARSING_M, + OUT_MAIL +}; + + + + +static inline int +mailmbox_single_parse(char * str, size_t length, + size_t * index, + size_t * pstart, + size_t * pstart_len, + size_t * pheaders, + size_t * pheaders_len, + size_t * pbody, + size_t * pbody_len, + size_t * psize, + size_t * ppadding, + uint32_t * puid) +{ + size_t cur_token; + size_t start; + size_t start_len; + size_t headers; + size_t headers_len; + size_t body; + size_t end; + size_t next; + size_t message_length; + uint32_t uid; + int r; +#if 0 + int in_mail_data; +#endif +#if 0 + size_t begin; +#endif + + int state; + + cur_token = * index; + + if (cur_token >= length) + return MAILMBOX_ERROR_PARSE; + + start = cur_token; + start_len = 0; + headers = cur_token; + + if (cur_token + 5 < length) { + if (strncmp(str + cur_token, "From ", 5) == 0) { + cur_token += 5; + while (str[cur_token] != '\n') { + cur_token ++; + if (cur_token >= length) + break; + } + if (cur_token < length) { + cur_token ++; + headers = cur_token; + start_len = headers - start; + } + } + } + + next = length; + + r = mailmbox_fields_parse(str, length, &cur_token, + &uid, &headers_len); + if (r != MAILMBOX_NO_ERROR) + return r; + + /* save position */ +#if 0 + begin = cur_token; +#endif + + mailimf_crlf_parse(str, length, &cur_token); + +#if 0 + if (str[cur_token] == 'F') { + printf("start !\n"); + printf("%50.50s\n", str + cur_token); + getchar(); + } +#endif + + body = cur_token; + + /* restore position */ + /* cur_token = begin; */ + + state = FIRST_LF; + + end = length; + +#if 0 + in_mail_data = 0; +#endif + while (state != OUT_MAIL) { + + if (cur_token >= length) { + if (state == IN_MAIL) + end = length; + next = length; + break; + } + + switch(state) { + case IN_MAIL: + switch(str[cur_token]) { + case '\r': + state = FIRST_CR; + break; + case '\n': + state = FIRST_LF; + break; + case 'F': + if (cur_token == body) { + end = cur_token; + next = cur_token; + state = PARSING_F; + } + break; +#if 0 + default: + in_mail_data = 1; + break; +#endif + } + break; + + case FIRST_CR: + end = cur_token; + switch(str[cur_token]) { + case '\r': + state = SECOND_CR; + break; + case '\n': + state = FIRST_LF; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case FIRST_LF: + end = cur_token; + switch(str[cur_token]) { + case '\r': + state = SECOND_CR; + break; + case '\n': + state = SECOND_LF; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case SECOND_CR: + switch(str[cur_token]) { + case '\r': + end = cur_token; + break; + case '\n': + state = SECOND_LF; + break; + case 'F': + next = cur_token; + state = PARSING_F; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case SECOND_LF: + switch(str[cur_token]) { + case '\r': + state = SECOND_CR; + break; + case '\n': + end = cur_token; + break; + case 'F': + next = cur_token; + state = PARSING_F; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case PARSING_F: + switch(str[cur_token]) { + case 'r': + state = PARSING_R; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case PARSING_R: + switch(str[cur_token]) { + case 'o': + state = PARSING_O; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case PARSING_O: + switch(str[cur_token]) { + case 'm': + state = PARSING_M; + break; + default: + state = IN_MAIL; +#if 0 + in_mail_data = 1; +#endif + break; + } + break; + + case PARSING_M: + switch(str[cur_token]) { + case ' ': + state = OUT_MAIL; + break; + default: + state = IN_MAIL; + break; + } + break; + } + + cur_token ++; + } + + message_length = end - start; + + * pstart = start; + * pstart_len = start_len; + * pheaders = headers; + * pheaders_len = headers_len; + * pbody = body; + * pbody_len = end - body; + * psize = message_length; + * ppadding = next - end; + * puid = uid; + + * index = next; + + return MAILMBOX_NO_ERROR; +} + + +int +mailmbox_parse_additionnal(struct mailmbox_folder * folder, + size_t * index) +{ + size_t cur_token; + + size_t start; + size_t start_len; + size_t headers; + size_t headers_len; + size_t body; + size_t body_len; + size_t size; + size_t padding; + uint32_t uid; + int r; + int res; + + uint32_t max_uid; + uint32_t first_index; + unsigned int i; + unsigned int j; + + cur_token = * index; + + /* remove temporary UID that we will parse */ + + first_index = carray_count(folder->mb_tab); + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + + if (info->msg_start < cur_token) { + continue; + } + + if (!info->msg_written_uid) { + chashdatum key; + + key.data = &info->msg_uid; + key.len = sizeof(info->msg_uid); + + chash_delete(folder->mb_hash, &key, NULL); + carray_delete_fast(folder->mb_tab, i); + mailmbox_msg_info_free(info); + if (i < first_index) + first_index = i; + } + } + + /* make a sequence in the table */ + + max_uid = folder->mb_written_uid; + + i = 0; + j = 0; + while (i < carray_count(folder->mb_tab)) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + if (info != NULL) { + carray_set(folder->mb_tab, j, info); + + if (info->msg_uid > max_uid) + max_uid = info->msg_uid; + + info->msg_index = j; + j ++; + } + i ++; + } + carray_set_size(folder->mb_tab, j); + + /* parse content */ + + first_index = j; + + while (1) { + struct mailmbox_msg_info * info; + chashdatum key; + chashdatum data; + + r = mailmbox_single_parse(folder->mb_mapping, folder->mb_mapping_size, + &cur_token, + &start, &start_len, + &headers, &headers_len, + &body, &body_len, + &size, &padding, &uid); + if (r == MAILMBOX_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILMBOX_ERROR_PARSE) + break; + else { + res = r; + goto err; + } + + key.data = &uid; + key.len = sizeof(uid); + + r = chash_get(folder->mb_hash, &key, &data); + if (r == 0) { + info = data.data; + + if (!info->msg_written_uid) { + /* some new mail has been written and override an + existing temporary UID */ + + chash_delete(folder->mb_hash, &key, NULL); + info->msg_uid = 0; + + if (info->msg_index < first_index) + first_index = info->msg_index; + } + else + uid = 0; + } + + if (uid > max_uid) + max_uid = uid; + + r = mailmbox_msg_info_update(folder, + start, start_len, headers, headers_len, + body, body_len, size, padding, uid); + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + } + + * index = cur_token; + + folder->mb_written_uid = max_uid; + + /* attribute uid */ + + for(i = first_index ; i < carray_count(folder->mb_tab) ; i ++) { + struct mailmbox_msg_info * info; + chashdatum key; + chashdatum data; + + info = carray_get(folder->mb_tab, i); + + if (info->msg_uid != 0) { + continue; + } + + max_uid ++; + info->msg_uid = max_uid; + + key.data = &info->msg_uid; + key.len = sizeof(info->msg_uid); + data.data = info; + data.len = 0; + + r = chash_set(folder->mb_hash, &key, &data, NULL); + if (r < 0) { + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + } + + folder->mb_max_uid = max_uid; + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + +static void flush_uid(struct mailmbox_folder * folder) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + if (info != NULL) + mailmbox_msg_info_free(info); + } + + chash_clear(folder->mb_hash); + carray_set_size(folder->mb_tab, 0); +} + +int mailmbox_parse(struct mailmbox_folder * folder) +{ + int r; + int res; + size_t cur_token; + + flush_uid(folder); + + cur_token = 0; + + r = mailmbox_parse_additionnal(folder, &cur_token); + + if (r != MAILMBOX_NO_ERROR) { + res = r; + goto err; + } + + return MAILMBOX_NO_ERROR; + + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox_parse.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox_parse.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmbox_parse.h,v 1.3 2004/11/21 21:53:38 hoa Exp $ + */ + +#ifndef MAILMBOX_PARSE_H + +#define MAILMBOX_PARSE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailmbox_types.h" + +int mailmbox_parse(struct mailmbox_folder * folder); + +int +mailmbox_parse_additionnal(struct mailmbox_folder * folder, + size_t * index); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox_types.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox_types.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,255 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmbox_types.c,v 1.22 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmbox_types.h" + +#include <string.h> +#include <stdlib.h> + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/* *********************************************************************** */ + +int mailmbox_msg_info_update(struct mailmbox_folder * folder, + size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid) +{ + struct mailmbox_msg_info * info; + int res; + chashdatum key; + chashdatum data; + int r; + + key.data = &msg_uid; + key.len = sizeof(msg_uid); + r = chash_get(folder->mb_hash, &key, &data); + if (r < 0) { + unsigned int index; + + info = mailmbox_msg_info_new(msg_start, msg_start_len, + msg_headers, msg_headers_len, + msg_body, msg_body_len, msg_size, msg_padding, msg_uid); + if (info == NULL) { + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + + r = carray_add(folder->mb_tab, info, &index); + if (r < 0) { + mailmbox_msg_info_free(info); + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + + if (msg_uid != 0) { + chashdatum key; + chashdatum data; + + key.data = &msg_uid; + key.len = sizeof(msg_uid); + data.data = info; + data.len = 0; + + r = chash_set(folder->mb_hash, &key, &data, NULL); + if (r < 0) { + mailmbox_msg_info_free(info); + carray_delete(folder->mb_tab, index); + res = MAILMBOX_ERROR_MEMORY; + goto err; + } + } + + info->msg_index = index; + } + else { + info = data.data; + + info->msg_start = msg_start; + info->msg_start_len = msg_start_len; + info->msg_headers = msg_headers; + info->msg_headers_len = msg_headers_len; + info->msg_body = msg_body; + info->msg_body_len = msg_body_len; + info->msg_size = msg_size; + info->msg_padding = msg_padding; + } + + return MAILMBOX_NO_ERROR; + + err: + return res; +} + + +struct mailmbox_msg_info * +mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid) +{ + struct mailmbox_msg_info * info; + + info = malloc(sizeof(* info)); + if (info == NULL) + return NULL; + + info->msg_index = 0; + info->msg_uid = msg_uid; + if (msg_uid != 0) + info->msg_written_uid = TRUE; + else + info->msg_written_uid = FALSE; + info->msg_deleted = FALSE; + + info->msg_start = msg_start; + info->msg_start_len = msg_start_len; + + info->msg_headers = msg_headers; + info->msg_headers_len = msg_headers_len; + + info->msg_body = msg_body; + info->msg_body_len = msg_body_len; + + info->msg_size = msg_size; + + info->msg_padding = msg_padding; + + return info; +} + +void mailmbox_msg_info_free(struct mailmbox_msg_info * info) +{ + free(info); +} + + +/* append info */ + +struct mailmbox_append_info * +mailmbox_append_info_new(const char * ai_message, size_t ai_size) +{ + struct mailmbox_append_info * info; + + info = malloc(sizeof(* info)); + if (info == NULL) + return NULL; + + info->ai_message = ai_message; + info->ai_size = ai_size; + info->ai_uid = 0; + + return info; +} + +void mailmbox_append_info_free(struct mailmbox_append_info * info) +{ + free(info); +} + +struct mailmbox_folder * mailmbox_folder_new(const char * mb_filename) +{ + struct mailmbox_folder * folder; + + folder = malloc(sizeof(* folder)); + if (folder == NULL) + goto err; + + strncpy(folder->mb_filename, mb_filename, PATH_MAX); + + folder->mb_mtime = (time_t) -1; + + folder->mb_fd = -1; + folder->mb_read_only = TRUE; + folder->mb_no_uid = TRUE; + + folder->mb_changed = FALSE; + folder->mb_deleted_count = 0; + + folder->mb_mapping = NULL; + folder->mb_mapping_size = 0; + + folder->mb_written_uid = 0; + folder->mb_max_uid = 0; + + folder->mb_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (folder->mb_hash == NULL) + goto free; + + folder->mb_tab = carray_new(128); + if (folder->mb_tab == NULL) + goto free_hash; + + return folder; + + free_hash: + chash_free(folder->mb_hash); + free: + free(folder); + err: + return NULL; +} + +void mailmbox_folder_free(struct mailmbox_folder * folder) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) { + struct mailmbox_msg_info * info; + + info = carray_get(folder->mb_tab, i); + if (info != NULL) + mailmbox_msg_info_free(info); + } + + carray_free(folder->mb_tab); + + chash_free(folder->mb_hash); + + free(folder); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mbox/mailmbox_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,143 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmbox_types.h,v 1.27 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILMBOX_TYPES_H + +#define MAILMBOX_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> + +#include <libetpan/libetpan-config.h> + +#include <libetpan/mailimf.h> +#include <libetpan/carray.h> +#include <libetpan/chash.h> + +enum { + MAILMBOX_NO_ERROR = 0, + MAILMBOX_ERROR_PARSE, + MAILMBOX_ERROR_INVAL, + MAILMBOX_ERROR_FILE_NOT_FOUND, + MAILMBOX_ERROR_MEMORY, + MAILMBOX_ERROR_TEMPORARY_FILE, + MAILMBOX_ERROR_FILE, + MAILMBOX_ERROR_MSG_NOT_FOUND, + MAILMBOX_ERROR_READONLY +}; + + +struct mailmbox_folder { + char mb_filename[PATH_MAX]; + + time_t mb_mtime; + + int mb_fd; + int mb_read_only; + int mb_no_uid; + + int mb_changed; + unsigned int mb_deleted_count; + + char * mb_mapping; + size_t mb_mapping_size; + + uint32_t mb_written_uid; + uint32_t mb_max_uid; + + chash * mb_hash; + carray * mb_tab; +}; + +struct mailmbox_folder * mailmbox_folder_new(const char * mb_filename); +void mailmbox_folder_free(struct mailmbox_folder * folder); + + +struct mailmbox_msg_info { + unsigned int msg_index; + uint32_t msg_uid; + int msg_written_uid; + int msg_deleted; + + size_t msg_start; + size_t msg_start_len; + + size_t msg_headers; + size_t msg_headers_len; + + size_t msg_body; + size_t msg_body_len; + + size_t msg_size; + + size_t msg_padding; +}; + + +int mailmbox_msg_info_update(struct mailmbox_folder * folder, + size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid); + +struct mailmbox_msg_info * +mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len, + size_t msg_headers, size_t msg_headers_len, + size_t msg_body, size_t msg_body_len, + size_t msg_size, size_t msg_padding, + uint32_t msg_uid); + +void mailmbox_msg_info_free(struct mailmbox_msg_info * info); + +struct mailmbox_append_info { + const char * ai_message; + size_t ai_size; + unsigned int ai_uid; +}; + +struct mailmbox_append_info * +mailmbox_append_info_new(const char * ai_message, size_t ai_size); + +void mailmbox_append_info_free(struct mailmbox_append_info * info); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/mh/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mh/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/low-level/mh/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mh/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,8 @@ +top_builddir = ../../.. + +HEADERS = mailmh.h +SOURCES = mailmh.c +TARGET = libmh +INCLUDES = -I$(srcdir)/data-types + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/low-level/mh/mailmh.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mh/mailmh.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1009 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmh.c,v 1.33 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmh.h" + +/* +perfs : + +/net/home/dinh/Mail/inbox/sylpheed 686 + +2724 /net/home/dinh/Mail/inbox/sylpheed + +bart:~/LibEtPan/libetpan/tests> time ./mhtest >/dev/null + +real 0m0.385s +user 0m0.270s +sys 0m0.110s + +*/ + +#ifdef _MSC_VER +# include "win_etpan.h" +#else +# include <dirent.h> +# include <unistd.h> +# include <sys/mman.h> +#endif +#include <sys/stat.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "libetpan-config.h" + +struct mailmh * mailmh_new(const char * foldername) +{ + struct mailmh * f; + + f = malloc(sizeof(*f)); + if (f == NULL) + return NULL; + + f->mh_main = mailmh_folder_new(NULL, foldername); + if (f->mh_main == NULL) { + free(f); + return NULL; + } + + return f; +} + +void mailmh_free(struct mailmh * f) +{ + mailmh_folder_free(f->mh_main); + free(f); +} + + + +struct mailmh_msg_info * mailmh_msg_info_new(uint32_t index, size_t size, + time_t mtime) +{ + struct mailmh_msg_info * msg_info; + + msg_info = malloc(sizeof(* msg_info)); + if (msg_info == NULL) + return NULL; + msg_info->msg_index = index; + msg_info->msg_size = size; + msg_info->msg_mtime = mtime; + + msg_info->msg_array_index = 0; + + return msg_info; +} + +void mailmh_msg_info_free(struct mailmh_msg_info * msg_info) +{ + free(msg_info); +} + +struct mailmh_folder * mailmh_folder_new(struct mailmh_folder * parent, + const char * name) +{ + char * filename; + char * parent_filename; + + struct mailmh_folder * folder; + + folder = malloc(sizeof(* folder)); + if (folder == NULL) + goto err; + + if (parent == NULL) { + filename = strdup(name); + if (filename == NULL) + goto free_folder; + } + else { + parent_filename = parent->fl_filename; + filename = malloc(strlen(parent_filename) + strlen(name) + 2); + if (filename == NULL) + goto free_folder; + + strcpy(filename, parent_filename); + strcat(filename, MAIL_DIR_SEPARATOR_S); + strcat(filename, name); + } + + folder->fl_filename = filename; + + folder->fl_name = strdup(name); + if (folder->fl_name == NULL) + goto free_filename; + + folder->fl_msgs_tab = carray_new(128); + if (folder->fl_msgs_tab == NULL) + goto free_name; + +#if 0 + folder->fl_msgs_hash = cinthash_new(128); + if (folder->fl_msgs_hash == NULL) + goto free_msgs_tab; +#endif + folder->fl_msgs_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); + if (folder->fl_msgs_hash == NULL) + goto free_msgs_tab; + + folder->fl_subfolders_tab = carray_new(128); + if (folder->fl_subfolders_tab == NULL) + goto free_msgs_hash; + + folder->fl_subfolders_hash = chash_new(128, CHASH_COPYNONE); + if (folder->fl_subfolders_hash == NULL) + goto free_subfolders_tab; + + folder->fl_mtime = 0; + folder->fl_parent = parent; + folder->fl_max_index = 0; + + return folder; + + free_subfolders_tab: + carray_free(folder->fl_subfolders_tab); + free_msgs_hash: +#if 0 + cinthash_free(folder->fl_msgs_hash); +#endif + chash_free(folder->fl_msgs_hash); + free_msgs_tab: + carray_free(folder->fl_msgs_tab); + free_name: + free(folder->fl_name); + free_filename: + free(folder->fl_filename); + free_folder: + free(folder); + err: + return NULL; +} + +void mailmh_folder_free(struct mailmh_folder * folder) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(folder->fl_subfolders_tab) ; i++) { + struct mailmh_folder * subfolder; + + subfolder = carray_get(folder->fl_subfolders_tab, i); + if (subfolder != NULL) + mailmh_folder_free(subfolder); + } + carray_free(folder->fl_subfolders_tab); + chash_free(folder->fl_subfolders_hash); + + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { + struct mailmh_msg_info * msg_info; + + msg_info = carray_get(folder->fl_msgs_tab, i); + if (msg_info != NULL) + mailmh_msg_info_free(msg_info); + } + carray_free(folder->fl_msgs_tab); + chash_free(folder->fl_msgs_hash); +#if 0 + cinthash_free(folder->fl_msgs_hash); +#endif + + free(folder->fl_filename); + free(folder->fl_name); + + free(folder); +} + +struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root, + const char * filename) +{ + int r; + char pathname[PATH_MAX]; + char * p; + chashdatum key; + chashdatum data; + struct mailmh_folder * folder; + char * start; + + if (strcmp(root->fl_filename, filename) == 0) + return root; + +#if 0 + r = mailmh_folder_update(root); + if (r != MAILMH_NO_ERROR) + return NULL; +#endif + +#if 0 + for(i = 0 ; i < root->fl_subfolders_tab->len ; i++) { + struct mailmh_folder * subfolder; + + subfolder = carray_get(root->fl_subfolders_tab, i); + if (subfolder != NULL) + if (strncmp(subfolder->fl_filename, filename, + strlen(subfolder->fl_filename)) == 0) + return mailmh_folder_find(subfolder, filename); + } +#endif + strncpy(pathname, filename, PATH_MAX); + pathname[PATH_MAX - 1] = 0; + start = pathname + strlen(root->fl_filename) + 1; + + p = strchr(start, MAIL_DIR_SEPARATOR); + if (p != NULL) { + * p = 0; + + root = mailmh_folder_find(root, pathname); + if (root != NULL) { + folder = mailmh_folder_find(root, filename); + if (folder == NULL) + return NULL; + return folder; + } + + return NULL; + } + else { + key.data = pathname; + key.len = strlen(pathname); + r = chash_get(root->fl_subfolders_hash, &key, &data); + if (r < 0) + return NULL; + + return data.data; + } +} + +int mailmh_folder_update(struct mailmh_folder * folder) +{ + DIR * d; + struct dirent * ent; + struct stat buf; + char * mh_seq; + char filename[PATH_MAX]; + int res; + int r; + uint32_t max_index; +#if 0 + int add_folder; +#endif + unsigned int i; + + if (stat(folder->fl_filename, &buf) == -1) { + res = MAILMH_ERROR_FOLDER; + goto err; + } + + if (folder->fl_mtime == buf.st_mtime) { + res = MAILMH_NO_ERROR; + goto err; + } + + folder->fl_mtime = buf.st_mtime; + + d = opendir(folder->fl_filename); + if (d == NULL) { + res = MAILMH_ERROR_FOLDER; + goto err; + } + + max_index = 0; + +#if 0 + if (folder->fl_subfolders_tab->len == 0) + add_folder = 1; + else + add_folder = 0; +#endif + + /* clear the message list */ + + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) { + struct mailmh_msg_info * msg_info; + chashdatum key; + + msg_info = carray_get(folder->fl_msgs_tab, i); + if (msg_info == NULL) + continue; + +#if 0 + cinthash_remove(folder->fl_msgs_hash, msg_info->msg_index); +#endif + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + chash_delete(folder->fl_msgs_hash, &key, NULL); + + mailmh_msg_info_free(msg_info); + } + + carray_set_size(folder->fl_msgs_tab, 0); + + do { + uint32_t index; + + ent = readdir(d); + + if (ent != NULL) { + + snprintf(filename, PATH_MAX, + "%s%c%s", folder->fl_filename, MAIL_DIR_SEPARATOR, ent->d_name); + + if (stat(filename, &buf) == -1) + continue; + + if (S_ISREG(buf.st_mode)) { + index = strtoul(ent->d_name, NULL, 10); + if (index != 0) { + struct mailmh_msg_info * msg_info; + unsigned int array_index; + chashdatum key; + chashdatum data; + + msg_info = mailmh_msg_info_new(index, buf.st_size, buf.st_mtime); + if (msg_info == NULL) { + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + + r = carray_add(folder->fl_msgs_tab, msg_info, &array_index); + if (r < 0) { + mailmh_msg_info_free(msg_info); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + msg_info->msg_array_index = array_index; + + if (index > max_index) + max_index = index; + +#if 0 + r = cinthash_add(folder->fl_msgs_hash, msg_info->msg_index, msg_info); +#endif + key.data = &msg_info->msg_index; + key.len = sizeof(msg_info->msg_index); + data.data = msg_info; + data.len = 0; + + r = chash_set(folder->fl_msgs_hash, &key, &data, NULL); + if (r < 0) { + carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); + mailmh_msg_info_free(msg_info); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + } + } + else if (S_ISDIR(buf.st_mode)) { + struct mailmh_folder * subfolder; + unsigned int array_index; + chashdatum key; + chashdatum data; + + if (ent->d_name[0] == '.') { + if (ent->d_name[1] == 0) + continue; + if ((ent->d_name[1] == '.') && (ent->d_name[2] == 0)) + continue; + } + + key.data = ent->d_name; + key.len = strlen(ent->d_name); + r = chash_get(folder->fl_subfolders_hash, &key, &data); + if (r < 0) { + subfolder = mailmh_folder_new(folder, ent->d_name); + if (subfolder == NULL) { + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + + r = carray_add(folder->fl_subfolders_tab, subfolder, &array_index); + if (r < 0) { + mailmh_folder_free(subfolder); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + subfolder->fl_array_index = array_index; + + key.data = subfolder->fl_filename; + key.len = strlen(subfolder->fl_filename); + data.data = subfolder; + data.len = 0; + r = chash_set(folder->fl_subfolders_hash, &key, &data, NULL); + if (r < 0) { + carray_delete_fast(folder->fl_subfolders_tab, subfolder->fl_array_index); + mailmh_folder_free(subfolder); + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + } + } + } + } + while (ent != NULL); + + folder->fl_max_index = max_index; + + mh_seq = malloc(strlen(folder->fl_filename) + 2 + sizeof(".mh_sequences")); + if (mh_seq == NULL) { + res = MAILMH_ERROR_MEMORY; + goto closedir; + } + strcpy(mh_seq, folder->fl_filename); + strcat(mh_seq, MAIL_DIR_SEPARATOR_S); + strcat(mh_seq, ".mh_sequences"); + + if (stat(mh_seq, &buf) == -1) { + int fd; + + fd = creat(mh_seq, S_IRUSR | S_IWUSR); + if (fd != -1) + close(fd); + } + free(mh_seq); + + closedir(d); + + return MAILMH_NO_ERROR; + + closedir: + closedir(d); + err: + return res; +} + +int mailmh_folder_add_subfolder(struct mailmh_folder * parent, + const char * name) +{ + char * foldername; + int r; + struct mailmh_folder * folder; + unsigned int array_index; + chashdatum key; + chashdatum data; + + foldername = malloc(strlen(parent->fl_filename) + strlen(name) + 2); + if (foldername == NULL) + return MAILMH_ERROR_MEMORY; + strcpy(foldername, parent->fl_filename); + strcat(foldername, MAIL_DIR_SEPARATOR_S); + strcat(foldername, name); + +#ifdef WIN32 + r = mkdir(foldername); +#else + r = mkdir(foldername, 0700); +#endif + free(foldername); + + if (r < 0) + return MAILMH_ERROR_FOLDER; + + folder = mailmh_folder_new(parent, name); + if (folder == NULL) + return MAILMH_ERROR_MEMORY; + + r = carray_add(parent->fl_subfolders_tab, folder, &array_index); + if (r < 0) { + mailmh_folder_free(folder); + return MAILMH_ERROR_MEMORY; + } + folder->fl_array_index = array_index; + + key.data = folder->fl_filename; + key.len = strlen(folder->fl_filename); + data.data = folder; + data.len = 0; + + r = chash_set(parent->fl_subfolders_hash, &key, &data, NULL); + if (r < 0) { + carray_delete_fast(folder->fl_subfolders_tab, folder->fl_array_index); + mailmh_folder_free(folder); + return MAILMH_ERROR_MEMORY; + } + + return MAILMH_NO_ERROR; +} + +int mailmh_folder_remove_subfolder(struct mailmh_folder * folder) +{ + struct mailmh_folder * parent; + chashdatum key; + chashdatum data; + int r; + + parent = folder->fl_parent; + + key.data = folder->fl_filename; + key.len = strlen(folder->fl_filename); + + r = chash_get(parent->fl_subfolders_hash, &key, &data); + if (r < 0) + return MAILMH_ERROR_FOLDER; + + chash_delete(parent->fl_subfolders_hash, &key, NULL); + carray_delete_fast(parent->fl_subfolders_tab, folder->fl_array_index); + + mailmh_folder_free(folder); + + return MAILMH_NO_ERROR; + +} + +int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder, + struct mailmh_folder * dst_folder, + const char * new_name) +{ + int r; + struct mailmh_folder * folder; + struct mailmh_folder * parent; + char * new_foldername; + + parent = src_folder->fl_parent; + if (parent == NULL) + return MAILMH_ERROR_RENAME; + + new_foldername = malloc(strlen(dst_folder->fl_filename) + 2 + strlen(new_name)); + if (new_foldername == NULL) + return MAILMH_ERROR_MEMORY; + + strcpy(new_foldername, dst_folder->fl_filename); + strcat(new_foldername, MAIL_DIR_SEPARATOR_S); + strcat(new_foldername, new_name); + + r = rename(src_folder->fl_filename, new_foldername); + free(new_foldername); + if (r < 0) + return MAILMH_ERROR_RENAME; + + r = mailmh_folder_remove_subfolder(src_folder); + if (r != MAILMH_NO_ERROR) + return r; + + folder = mailmh_folder_new(dst_folder, new_name); + if (folder == NULL) + return MAILMH_ERROR_MEMORY; + + r = carray_add(parent->fl_subfolders_tab, folder, NULL); + if (r < 0) { + mailmh_folder_free(folder); + return MAILMH_ERROR_MEMORY; + } + + return MAILMH_NO_ERROR; +} + +#define MAX_TRY_ALLOC 32 + +/* initial file MUST be in the same directory */ + +static int mailmh_folder_alloc_msg(struct mailmh_folder * folder, + char * filename, uint32_t * result) +{ + uint32_t max; + uint32_t k; + char * new_filename; + size_t len; + int got_file; + int r; + + len = strlen(folder->fl_filename) + 20; + new_filename = malloc(len); + if (new_filename == NULL) + return MAILMH_ERROR_MEMORY; + + max = folder->fl_max_index + 1; + + got_file = 0; + k = 0; + while (k < MAX_TRY_ALLOC) { + snprintf(new_filename, len, "%s%c%lu", folder->fl_filename, + MAIL_DIR_SEPARATOR, (unsigned long) (max + k)); + +/* SEB */ +#ifdef WIN32 + if (rename( filename, new_filename) == 0) { + got_file = 1; + } +#else + if (link(filename, new_filename) == 0) { + unlink(filename); + got_file = 1; + } +#endif /* WIN32 */ + else if (errno == EXDEV) { + free(filename); + return MAILMH_ERROR_FOLDER; + } + else if (errno == EPERM) { + rename(filename, new_filename); + got_file = 1; + } + + if (got_file) { + free(new_filename); + + if (k > MAX_TRY_ALLOC / 2) { + r = mailmh_folder_update(folder); + /* ignore errors */ + } + + * result = max + k; + + folder->fl_max_index = max + k; + + return MAILMH_NO_ERROR; + } + k ++; + } + + free(new_filename); + + return MAILMH_ERROR_FOLDER; +} + +int mailmh_folder_get_message_filename(struct mailmh_folder * folder, + uint32_t index, char ** result) +{ + char * filename; + int len; + +#if 0 + r = mailmh_folder_update(folder); + if (r != MAILMH_NO_ERROR) + return r; +#endif + + len = strlen(folder->fl_filename) + 20; + filename = malloc(len); + if (filename == NULL) + return MAILMH_ERROR_MEMORY; + + snprintf(filename, len, "%s%c%lu", folder->fl_filename, MAIL_DIR_SEPARATOR, + (unsigned long) index); + + * result = filename; + + return MAILMH_NO_ERROR;; +} + + +int mailmh_folder_get_message_fd(struct mailmh_folder * folder, + uint32_t index, int flags, int * result) +{ + char * filename; + int fd; + int r; + +#if 0 + r = mailmh_folder_update(folder); + if (r != MAILMH_NO_ERROR) + return r; +#endif + + r = mailmh_folder_get_message_filename(folder, index, &filename); + if (r != MAILMH_NO_ERROR) + return r; + + fd = open(filename, flags); + free(filename); + if (fd == -1) + return MAILMH_ERROR_MSG_NOT_FOUND; + + * result = fd; + + return MAILMH_NO_ERROR; +} + +int mailmh_folder_get_message_size(struct mailmh_folder * folder, + uint32_t index, size_t * result) +{ + int r; + char * filename; + struct stat buf; + + r = mailmh_folder_get_message_filename(folder, index, &filename); + if (r != MAILMH_NO_ERROR) + return r; + + r = stat(filename, &buf); + free(filename); + if (r < 0) + return MAILMH_ERROR_FILE; + + * result = buf.st_size; + + return MAILMH_NO_ERROR; +} + +int mailmh_folder_add_message_uid(struct mailmh_folder * folder, + const char * message, size_t size, + uint32_t * pindex) +{ + char * tmpname; + int fd; + size_t namesize; + size_t left; + ssize_t res; + struct mailmh_msg_info * msg_info; + uint32_t index; + int error; + int r; + unsigned int array_index; + struct stat buf; + chashdatum key; + chashdatum data; + +#if 0 + r = mailmh_folder_update(folder); + if (r != MAILMH_NO_ERROR) { + error = r; + goto err; + } +#endif + + namesize = strlen(folder->fl_filename) + 20; + tmpname = malloc(namesize); + snprintf(tmpname, namesize, "%s%ctmpXXXXXX", + folder->fl_filename, MAIL_DIR_SEPARATOR); + fd = mkstemp(tmpname); + if (fd < 0) { + error = MAILMH_ERROR_FILE; + goto free; + } + + left = size; + while (left > 0) { + res = write(fd, message, left); + if (res == -1) { + close(fd); + error = MAILMH_ERROR_FILE; + goto free; + } + + left -= res; + } + close(fd); + + r = stat(tmpname, &buf); + if (r < 0) { + error = MAILMH_ERROR_FILE; + goto free; + } + + r = mailmh_folder_alloc_msg(folder, tmpname, &index); + if (r != MAILMH_NO_ERROR) { + unlink(tmpname); + error = MAILMH_ERROR_COULD_NOT_ALLOC_MSG; + goto free; + } + free(tmpname); + + msg_info = mailmh_msg_info_new(index, size, buf.st_mtime); + if (msg_info == NULL) { + mailmh_folder_remove_message(folder, index); + error = MAILMH_ERROR_MEMORY; + goto err; + } + + r = carray_add(folder->fl_msgs_tab, msg_info, &array_index); + if (r < 0) { + mailmh_folder_remove_message(folder, index); + mailmh_msg_info_free(msg_info); + error = MAILMH_ERROR_MEMORY; + goto err; + } + msg_info->msg_array_index = array_index; + +#if 0 + r = cinthash_add(folder->fl_msgs_hash, index, msg_info); +#endif + key.data = &index; + key.len = sizeof(index); + data.data = msg_info; + data.len = 0; + + if (pindex != NULL) + * pindex = index; + + r = chash_set(folder->fl_msgs_hash, &key, &data, NULL); + if (r < 0) { + carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); + mailmh_msg_info_free(msg_info); + error = MAILMH_ERROR_MEMORY; + goto err; + } + + return MAILMH_NO_ERROR; + + free: + free(tmpname); + err: + return error; +} + +int mailmh_folder_add_message(struct mailmh_folder * folder, + const char * message, size_t size) +{ + return mailmh_folder_add_message_uid(folder, message, size, NULL); +} + +int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder, + int fd, uint32_t * pindex) +{ + char * message; + struct stat buf; + int r; + +#if 0 + r = mailmh_folder_update(folder); + if (r != MAILMH_NO_ERROR) + return r; +#endif + + if (fstat(fd, &buf) == -1) + return MAILMH_ERROR_FILE; + + message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (message == (const char *)MAP_FAILED) + return MAILMH_ERROR_FILE; + + r = mailmh_folder_add_message_uid(folder, message, buf.st_size, pindex); + + munmap(message, buf.st_size); + + return r; +} + +int mailmh_folder_add_message_file(struct mailmh_folder * folder, + int fd) +{ + return mailmh_folder_add_message_file_uid(folder, fd, NULL); +} + +int mailmh_folder_remove_message(struct mailmh_folder * folder, + uint32_t index) +{ + char * filename; + struct mailmh_msg_info * msg_info; + int res; + int r; + chashdatum key; + chashdatum data; + +#if 0 + r = mailmh_folder_update(folder); + if (r != MAILMH_NO_ERROR) { + res = r; + goto err; + } +#endif + + r = mailmh_folder_get_message_filename(folder, index, &filename); + if (filename == NULL) { + res = r; + goto err; + } + + if (unlink(filename) == -1) { + res = MAILMH_ERROR_FILE; + goto free; + } + + key.data = &index; + key.len = sizeof(index); + r = chash_get(folder->fl_msgs_hash, &key, &data); +#if 0 + msg_info = cinthash_find(folder->fl_msgs_hash, index); +#endif + if (r == 0) { + msg_info = data.data; + + carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); +#if 0 + cinthash_remove(folder->fl_msgs_hash, index); +#endif + chash_delete(folder->fl_msgs_hash, &key, NULL); + } + + return MAILMH_NO_ERROR; + + free: + free(filename); + err: + return res; +} + + +int mailmh_folder_move_message(struct mailmh_folder * dest_folder, + struct mailmh_folder * src_folder, + uint32_t index) +{ + int fd; + char * filename; + int r; + +#if 0 + r = mailmh_folder_update(dest_folder); + if (r != MAILMH_NO_ERROR) + return r; + r = mailmh_folder_update(src_folder); + if (r != MAILMH_NO_ERROR) + return r; +#endif + + /* move on the same filesystem */ + r = mailmh_folder_get_message_filename(src_folder, index, &filename); + if (r != MAILMH_NO_ERROR) + return r; + + r = mailmh_folder_alloc_msg(dest_folder, filename, &index); + free(filename); + if (r == MAILMH_NO_ERROR) + return MAILMH_NO_ERROR; + + /* move on the different filesystems */ + r = mailmh_folder_get_message_fd(src_folder, index, O_RDONLY, &fd); + if (r != MAILMH_NO_ERROR) + return r; + + r = mailmh_folder_add_message_file(dest_folder, fd); + if (r != MAILMH_NO_ERROR) { + close(fd); + return r; + } + + close(fd); + + r = mailmh_folder_remove_message(src_folder, index); + + return MAILMH_NO_ERROR; +} + +unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder) +{ + unsigned int i; + unsigned int count; + + count = 0; + for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) + if (carray_get(folder->fl_msgs_tab, i) != NULL) + count ++; + + return count; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/mh/mailmh.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mh/mailmh.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,150 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmh.h,v 1.26 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILMH_H + +#define MAILMH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> + +#include <libetpan/libetpan-config.h> +#include <libetpan/carray.h> +#include <libetpan/chash.h> + +enum { + MAILMH_NO_ERROR = 0, + MAILMH_ERROR_FOLDER, + MAILMH_ERROR_MEMORY, + MAILMH_ERROR_FILE, + MAILMH_ERROR_COULD_NOT_ALLOC_MSG, + MAILMH_ERROR_RENAME, + MAILMH_ERROR_MSG_NOT_FOUND +}; + +struct mailmh { + struct mailmh_folder * mh_main; +}; + +struct mailmh_msg_info { + unsigned int msg_array_index; + uint32_t msg_index; + size_t msg_size; + time_t msg_mtime; +}; + +struct mailmh_folder { + char * fl_filename; + unsigned int fl_array_index; + + char * fl_name; + time_t fl_mtime; + struct mailmh_folder * fl_parent; + uint32_t fl_max_index; + + carray * fl_msgs_tab; +#if 0 + cinthash_t * fl_msgs_hash; +#endif + chash * fl_msgs_hash; + + carray * fl_subfolders_tab; + chash * fl_subfolders_hash; +}; + +struct mailmh * mailmh_new(const char * foldername); +void mailmh_free(struct mailmh * f); + +struct mailmh_msg_info * +mailmh_msg_info_new(uint32_t index, size_t size, time_t mtime); +void mailmh_msg_info_free(struct mailmh_msg_info * msg_info); + +struct mailmh_folder * mailmh_folder_new(struct mailmh_folder * parent, + const char * name); +void mailmh_folder_free(struct mailmh_folder * folder); + +int mailmh_folder_add_subfolder(struct mailmh_folder * parent, + const char * name); + +struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root, + const char * filename); + +int mailmh_folder_remove_subfolder(struct mailmh_folder * folder); + +int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder, + struct mailmh_folder * dst_folder, + const char * new_name); + +int mailmh_folder_get_message_filename(struct mailmh_folder * folder, + uint32_t index, char ** result); + +int mailmh_folder_get_message_fd(struct mailmh_folder * folder, + uint32_t index, int flags, int * result); + +int mailmh_folder_get_message_size(struct mailmh_folder * folder, + uint32_t index, size_t * result); + +int mailmh_folder_add_message_uid(struct mailmh_folder * folder, + const char * message, size_t size, + uint32_t * pindex); + +int mailmh_folder_add_message(struct mailmh_folder * folder, + const char * message, size_t size); + +int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder, + int fd, uint32_t * pindex); + +int mailmh_folder_add_message_file(struct mailmh_folder * folder, + int fd); + +int mailmh_folder_remove_message(struct mailmh_folder * folder, + uint32_t index); + +int mailmh_folder_move_message(struct mailmh_folder * dest_folder, + struct mailmh_folder * src_folder, + uint32_t index); + +int mailmh_folder_update(struct mailmh_folder * folder); + +unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,14 @@ +top_builddir = ../../.. + +HEADERS = mailmime.h mailmime_types.h mailmime_content.h mailmime_decode.h \ + mailmime_disposition.h mailmime_write_file.h \ + mailmime_types_helper.h mailmime_write_generic.h \ + mailmime_write_mem.h +SOURCES = mailmime.c mailmime_types.c mailmime_content.c mailmime_decode.c \ + mailmime_disposition.c mailmime_write_file.c \ + mailmime_types_helper.c mailmime_write_generic.c \ + mailmime_write_mem.c +TARGET = libmime +INCLUDES = -I../imf -I$(srcdir)/data-types + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/TODO ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/TODO Wed Dec 20 15:28:56 2006 @@ -0,0 +1,10 @@ +- see about the RFC2047, beginning in mailmime_decode.[ch] +- content-langage +- single mime_field +- RFC 2048 +- RFC 2049 +- RFC 2231 +- RFC 2387 +- RFC 2424 +- RFC 2557 + Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1425 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime.c,v 1.27 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmime.h" + +/* + RFC 2045 + RFC 2046 + RFC 2047 + RFC 2048 + RFC 2049 + RFC 2231 + RFC 2387 + RFC 2424 + RFC 2557 + + RFC 2183 Content-Disposition + + RFC 1766 Language + */ + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> + +#include "mailmime_types.h" +#include "mailmime_disposition.h" +#include "mailimf.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +static int mailmime_attribute_parse(const char * message, size_t length, + size_t * index, + char ** result); +static int +mailmime_composite_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_composite_type ** result); + +static int is_text(char ch); + +static int +mailmime_discrete_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_discrete_type ** result); + +static int mailmime_mechanism_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result); + +static int mailmime_subtype_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int is_token(char ch); + +static int mailmime_token_parse(const char * message, size_t length, + size_t * index, + char ** token); + +static int is_tspecials(char ch); + +static int mailmime_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_type ** result); + +/* +int mailmime_version_parse(const char * message, guint32 length, + guint32 * index, + guint32 * result); +*/ + +/* +static gboolean mailmime_x_token_parse(gconst char * message, guint32 length, + guint32 * index, + gchar ** result); +*/ + +/* ********************************************************************** */ + +/* +x attribute := token + ; Matching of attributes + ; is ALWAYS case-insensitive. +*/ + +static int mailmime_attribute_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + return mailmime_token_parse(message, length, index, result); +} + +/* +x composite-type := "message" / "multipart" / extension-token +*/ + +static int +mailmime_composite_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_composite_type ** result) +{ + char * extension_token; + int type; + struct mailmime_composite_type * ct; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + extension_token = NULL; + + type = MAILMIME_COMPOSITE_TYPE_ERROR; /* XXX - removes a gcc warning */ + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "message"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_COMPOSITE_TYPE_MESSAGE; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "multipart"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_COMPOSITE_TYPE_MULTIPART; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + ct = mailmime_composite_type_new(type, extension_token); + if (ct == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_extension; + } + + * result = ct; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_extension: + if (extension_token != NULL) + mailmime_extension_token_free(extension_token); + err: + return res; +} + +/* +x content := "Content-Type" ":" type "/" subtype + *(";" parameter) + ; Matching of media type and subtype + ; is ALWAYS case-insensitive. +*/ + +LIBETPAN_EXPORT +int mailmime_content_parse(const char * message, size_t length, + size_t * index, + struct mailmime_content ** result) +{ + size_t cur_token; + struct mailmime_type * type; + char * subtype; + clist * parameters_list; + struct mailmime_content * content; + int r; + int res; + + cur_token = * index; + + mailimf_cfws_parse(message, length, &cur_token); + + type = NULL; + r = mailmime_type_parse(message, length, &cur_token, &type); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '/'); + switch (r) { + case MAILIMF_NO_ERROR: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_type; + } + + r = mailmime_subtype_parse(message, length, &cur_token, &subtype); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_type; + } + break; + + case MAILIMF_ERROR_PARSE: + subtype = strdup("unknown"); + break; + + default: + res = r; + goto free_type; + } + + parameters_list = clist_new(); + if (parameters_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_type; + } + + while (1) { + size_t final_token; + struct mailmime_parameter * parameter; + + final_token = cur_token; + r = mailimf_unstrict_char_parse(message, length, &cur_token, ';'); + if (r != MAILIMF_NO_ERROR) { + cur_token = final_token; + break; + } + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_type; + } + + r = mailmime_parameter_parse(message, length, &cur_token, ¶meter); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + cur_token = final_token; + break; + } + else { + res = r; + goto err; + } + + r = clist_append(parameters_list, parameter); + if (r < 0) { + mailmime_parameter_free(parameter); + res = MAILIMF_ERROR_MEMORY; + goto free_parameters; + } + } + + content = mailmime_content_new(type, subtype, parameters_list); + if (content == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_parameters; + } + + * result = content; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_parameters: + clist_foreach(parameters_list, (clist_func) mailmime_parameter_free, NULL); + clist_free(parameters_list); + + mailmime_subtype_free(subtype); + free_type: + mailmime_type_free(type); + err: + return res; +} + +/* +x description := "Content-Description" ":" *text +*/ + +static int is_text(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (uch < 1) + return FALSE; + + if ((uch == 10) || (uch == 13)) + return FALSE; + + return TRUE; +} + +LIBETPAN_EXPORT +int mailmime_description_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + return mailimf_custom_string_parse(message, length, + index, result, + is_text); +} + +/* +x discrete-type := "text" / "image" / "audio" / "video" / + "application" / extension-token +*/ + +/* currently porting */ + +static int +mailmime_discrete_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_discrete_type ** result) +{ + char * extension; + int type; + struct mailmime_discrete_type * discrete_type; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + extension = NULL; + + type = MAILMIME_DISCRETE_TYPE_ERROR; /* XXX - removes a gcc warning */ + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "text"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_TEXT; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "image"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_IMAGE; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "audio"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_AUDIO; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "video"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_VIDEO; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "application"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_APPLICATION; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_extension_token_parse(message, length, + &cur_token, &extension); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_EXTENSION; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + discrete_type = mailmime_discrete_type_new(type, extension); + if (discrete_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = discrete_type; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + mailmime_extension_token_free(extension); + err: + return res; +} + +/* +x encoding := "Content-Transfer-Encoding" ":" mechanism +*/ + +LIBETPAN_EXPORT +int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result) +{ + return mailmime_mechanism_parse(message, length, index, result); +} + +/* +x entity-headers := [ content CRLF ] + [ encoding CRLF ] + [ id CRLF ] + [ description CRLF ] + *( MIME-extension-field CRLF ) + */ + +enum { + FIELD_STATE_START, + FIELD_STATE_T, + FIELD_STATE_D +}; + +static int guess_field_type(char * name) +{ + int state; + + if (* name == 'M') + return MAILMIME_FIELD_VERSION; + + if (strncasecmp(name, "Content-", 8) != 0) + return MAILMIME_FIELD_NONE; + + name += 8; + + state = FIELD_STATE_START; + + while (1) { + + switch (state) { + + case FIELD_STATE_START: + switch ((char) toupper((unsigned char) * name)) { + case 'T': + state = FIELD_STATE_T; + break; + case 'I': + return MAILMIME_FIELD_ID; + case 'D': + state = FIELD_STATE_D; + break; + case 'L': + return MAILMIME_FIELD_LANGUAGE; + default: + return MAILMIME_FIELD_NONE; + } + break; + + case FIELD_STATE_T: + switch ((char) toupper((unsigned char) * name)) { + case 'Y': + return MAILMIME_FIELD_TYPE; + case 'R': + return MAILMIME_FIELD_TRANSFER_ENCODING; + default: + return MAILMIME_FIELD_NONE; + } + break; + + case FIELD_STATE_D: + switch ((char) toupper((unsigned char) * name)) { + case 'E': + return MAILMIME_FIELD_DESCRIPTION; + case 'I': + return MAILMIME_FIELD_DISPOSITION; + default: + return MAILMIME_FIELD_NONE; + } + break; + } + name ++; + } +} + +LIBETPAN_EXPORT +int +mailmime_field_parse(struct mailimf_optional_field * field, + struct mailmime_field ** result) +{ + char * name; + char * value; + int guessed_type; + size_t cur_token; + struct mailmime_content * content; + struct mailmime_mechanism * encoding; + char * id; + char * description; + uint32_t version; + struct mailmime_field * mime_field; + struct mailmime_language * language; + struct mailmime_disposition * disposition; + int res; + int r; + + name = field->fld_name; + value = field->fld_value; + cur_token = 0; + + content = NULL; + encoding = NULL; + id = NULL; + description = NULL; + version = 0; + disposition = NULL; + language = NULL; + + guessed_type = guess_field_type(name); + + switch (guessed_type) { + case MAILMIME_FIELD_TYPE: + if (strcasecmp(name, "Content-Type") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_content_parse(value, strlen(value), &cur_token, &content); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_TRANSFER_ENCODING: + if (strcasecmp(name, "Content-Transfer-Encoding") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_encoding_parse(value, strlen(value), &cur_token, &encoding); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_ID: + if (strcasecmp(name, "Content-ID") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_id_parse(value, strlen(value), &cur_token, &id); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_DESCRIPTION: + if (strcasecmp(name, "Content-Description") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_description_parse(value, strlen(value), + &cur_token, &description); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_VERSION: + if (strcasecmp(name, "MIME-Version") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_version_parse(value, strlen(value), &cur_token, &version); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_DISPOSITION: + if (strcasecmp(name, "Content-Disposition") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_disposition_parse(value, strlen(value), + &cur_token, &disposition); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_LANGUAGE: + if (strcasecmp(name, "Content-Language") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_language_parse(value, strlen(value), &cur_token, &language); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + default: + return MAILIMF_ERROR_PARSE; + } + + mime_field = mailmime_field_new(guessed_type, content, encoding, + id, description, version, disposition, + language); + if (mime_field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mime_field; + + return MAILIMF_NO_ERROR; + + free: + if (content != NULL) + mailmime_content_free(content); + if (encoding != NULL) + mailmime_encoding_free(encoding); + if (id != NULL) + mailmime_id_free(id); + if (description != NULL) + mailmime_description_free(description); + return res; +} + +/* +x extension-token := ietf-token / x-token +*/ + +LIBETPAN_EXPORT +int +mailmime_extension_token_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailmime_token_parse(message, length, index, result); +} + +/* + hex-octet := "=" 2(DIGIT / "A" / "B" / "C" / "D" / "E" / "F") + ; Octet must be used for characters > 127, =, + ; SPACEs or TABs at the ends of lines, and is + ; recommended for any character not listed in + ; RFC 2049 as "mail-safe". +*/ + +/* +x iana-token := <A publicly-defined extension token. Tokens + of this form must be registered with IANA + as specified in RFC 2048.> +*/ + +/* +x ietf-token := <An extension token defined by a + standards-track RFC and registered + with IANA.> +*/ + +/* +x id := "Content-ID" ":" msg-id +*/ + +LIBETPAN_EXPORT +int mailmime_id_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_msg_id_parse(message, length, index, result); +} + +/* +x mechanism := "7bit" / "8bit" / "binary" / + "quoted-printable" / "base64" / + ietf-token / x-token +*/ + +static int mailmime_mechanism_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result) +{ + char * token; + int type; + struct mailmime_mechanism * mechanism; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + type = MAILMIME_MECHANISM_ERROR; /* XXX - removes a gcc warning */ + + token = NULL; + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "7bit"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_7BIT; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "8bit"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_8BIT; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "binary"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_BINARY; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "quoted-printable"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "base64"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_BASE64; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_token_parse(message, length, &cur_token, &token); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_TOKEN; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mechanism = mailmime_mechanism_new(type, token); + if (mechanism == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mechanism; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (token != NULL) + mailmime_token_free(token); + err: + return res; +} + +/* +x MIME-extension-field := <Any RFC 822 header field which + begins with the string + "Content-"> +*/ + +/* +in headers + +x MIME-message-headers := entity-headers + fields + version CRLF + ; The ordering of the header + ; fields implied by this BNF + ; definition should be ignored. +*/ + +/* +in message + +x MIME-part-headers := entity-headers + [fields] + ; Any field not beginning with + ; "content-" can have no defined + ; meaning and may be ignored. + ; The ordering of the header + ; fields implied by this BNF + ; definition should be ignored. +*/ + +#if 0 +LIBETPAN_EXPORT +int +mailmime_unparsed_fields_parse(struct mailimf_unparsed_fields * + fields, + struct mailmime_fields ** + result) +{ + clistiter * cur; + struct mailmime_fields * mime_fields; + clist * list; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + if (fields->list == NULL) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + for(cur = clist_begin(fields->list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_optional_field * field = cur->data; + struct mailmime_field * mime_field; + + r = mailmime_field_parse(field, &mime_field); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, mime_field); + if (r < 0) { + mailmime_field_free(mime_field); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + } + } + + if (clist_begin(list) == NULL) { + res = MAILIMF_ERROR_PARSE; + goto free_list; + } + + mime_fields = mailmime_fields_new(list); + if (mime_fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = mime_fields; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_field_free, NULL); + clist_free(list); + err: + return res; +} +#endif + +LIBETPAN_EXPORT +int +mailmime_fields_parse(struct mailimf_fields * + fields, + struct mailmime_fields ** + result) +{ + clistiter * cur; + struct mailmime_fields * mime_fields; + clist * list; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_field * field; + struct mailmime_field * mime_field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + r = mailmime_field_parse(field->fld_data.fld_optional_field, + &mime_field); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, mime_field); + if (r < 0) { + mailmime_field_free(mime_field); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free_list; + } + } + } + + if (clist_begin(list) == NULL) { + res = MAILIMF_ERROR_PARSE; + goto free_list; + } + + mime_fields = mailmime_fields_new(list); + if (mime_fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = mime_fields; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_field_free, NULL); + clist_free(list); + err: + return res; +} + +/* +x parameter := attribute "=" value +*/ + +LIBETPAN_EXPORT +int mailmime_parameter_parse(const char * message, size_t length, + size_t * index, + struct mailmime_parameter ** result) +{ + char * attribute; + char * value; + struct mailmime_parameter * parameter; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailmime_attribute_parse(message, length, &cur_token, &attribute); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_attr; + } + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_attr; + } + + r = mailmime_value_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_attr; + } + + parameter = mailmime_parameter_new(attribute, value); + if (parameter == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = parameter; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailmime_value_free(value); + free_attr: + mailmime_attribute_free(attribute); + err: + return res; +} + +/* + ptext := hex-octet / safe-char +*/ + +/* + qp-line := *(qp-segment transport-padding CRLF) + qp-part transport-padding +*/ + +/* + qp-part := qp-section + ; Maximum length of 76 characters +*/ + +/* + qp-section := [*(ptext / SPACE / TAB) ptext] +*/ + +/* + qp-segment := qp-section *(SPACE / TAB) "=" + ; Maximum length of 76 characters +*/ + +/* + quoted-printable := qp-line *(CRLF qp-line) +*/ + +/* + safe-char := <any octet with decimal value of 33 through + 60 inclusive, and 62 through 126> + ; Characters not listed as "mail-safe" in + ; RFC 2049 are also not recommended. +*/ + +/* +x subtype := extension-token / iana-token +*/ + +static int mailmime_subtype_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailmime_extension_token_parse(message, length, index, result); +} + +/* +x token := 1*<any (US-ASCII) CHAR except SPACE, CTLs, + or tspecials> +*/ + +static int is_token(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (uch > 0x7F) + return FALSE; + + if (uch == ' ') + return FALSE; + + if (is_tspecials(ch)) + return FALSE; + + return TRUE; +} + + +static int mailmime_token_parse(const char * message, size_t length, + size_t * index, + char ** token) +{ + return mailimf_custom_string_parse(message, length, + index, token, + is_token); +} + +/* + transport-padding := *LWSP-char + ; Composers MUST NOT generate + ; non-zero length transport + ; padding, but receivers MUST + ; be able to handle padding + ; added by message transports. +*/ + +/* +enum { + LWSP_1, + LWSP_2, + LWSP_3, + LWSP_4, + LWSP_OK +}; + +gboolean mailmime_transport_padding_parse(gconst char * message, guint32 length, + guint32 * index) +{ + guint32 cur_token; + gint state; + guint32 last_valid_pos; + + cur_token = * index; + + if (cur_token >= length) + return FALSE; + + state = LWSP_1; + + while (state != LWSP_OUT) { + + if (cur_token >= length) + return FALSE; + + switch (state) { + case LWSP_1: + last_valid_pos = cur_token; + + switch (message[cur_token]) { + case '\r': + state = LWSP_2; + break; + case '\n': + state = LWSP_3; + break; + case ' ': + case '\t': + state = LWSP_4; + break; + default: + state = LWSP_OK; + break; + } + case LWSP_2: + switch (message[cur_token]) { + case '\n': + state = LWSP_3; + break; + default: + state = LWSP_OUT; + cur_token = last_valid_pos; + break; + } + case LWSP_3: + switch (message[cur_token]) { + case ' ': + case '\t': + state = LWSP_1; + break; + default: + state = LWSP_OUT; + cur_token = last_valid_pos; + break; + } + + cur_token ++; + } + } + + * index = cur_token; + + return TRUE; +} +*/ + +/* +x tspecials := "(" / ")" / "<" / ">" / "@" / + "," / ";" / ":" / "\" / <"> + "/" / "[" / "]" / "?" / "=" + ; Must be in quoted-string, + ; to use within parameter values +*/ + +static int is_tspecials(char ch) +{ + switch (ch) { + case '(': + case ')': + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '\\': + case '\"': + case '/': + case '[': + case ']': + case '?': + case '=': + return TRUE; + default: + return FALSE; + } +} + +/* +x type := discrete-type / composite-type +*/ + +static int mailmime_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_type ** result) +{ + struct mailmime_discrete_type * discrete_type; + struct mailmime_composite_type * composite_type; + size_t cur_token; + struct mailmime_type * mime_type; + int type; + int res; + int r; + + cur_token = * index; + + discrete_type = NULL; + composite_type = NULL; + + type = MAILMIME_TYPE_ERROR; /* XXX - removes a gcc warning */ + + r = mailmime_composite_type_parse(message, length, &cur_token, + &composite_type); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_TYPE_COMPOSITE_TYPE; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_discrete_type_parse(message, length, &cur_token, + &discrete_type); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_TYPE_DISCRETE_TYPE; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mime_type = mailmime_type_new(type, discrete_type, composite_type); + if (mime_type == NULL) { + res = r; + goto free; + } + + * result = mime_type; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (discrete_type != NULL) + mailmime_discrete_type_free(discrete_type); + if (composite_type != NULL) + mailmime_composite_type_free(composite_type); + err: + return res; +} + +/* +x value := token / quoted-string +*/ + +LIBETPAN_EXPORT +int mailmime_value_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + int r; + + r = mailmime_token_parse(message, length, index, result); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_quoted_string_parse(message, length, index, result); + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +/* +x version := "MIME-Version" ":" 1*DIGIT "." 1*DIGIT +*/ + +LIBETPAN_EXPORT +int mailmime_version_parse(const char * message, size_t length, + size_t * index, + uint32_t * result) +{ + size_t cur_token; + uint32_t hi; + uint32_t low; + uint32_t version; + int r; + + cur_token = * index; + + r = mailimf_number_parse(message, length, &cur_token, &hi); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '.'); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &low); + if (r != MAILIMF_NO_ERROR) + return r; + + version = (hi << 16) + low; + + * result = version; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +x x-token := <The two characters "X-" or "x-" followed, with + no intervening white space, by any token> +*/ + +/* +static gboolean mailmime_x_token_parse(gconst char * message, guint32 length, + guint32 * index, + gchar ** result) +{ + guint32 cur_token; + gchar * token; + gchar * x_token; + gboolean min_x; + + cur_token = * index; + + if (!mailimf_char_parse(message, length, &cur_token, 'x')) { + if (!mailimf_char_parse(message, length, &cur_token, 'X')) + return FALSE; + min_x = FALSE; + } + else + min_x = TRUE; + + if (!mailimf_char_parse(message, length, &cur_token, '-')) + return FALSE; + + if (!mailmime_token_parse(message, length, &cur_token, &token)) + return FALSE; + + if (min_x) + x_token = g_strconcat("x-", token, NULL); + else + x_token = g_strconcat("X-", token, NULL); + mailmime_token_free(token); + + if (x_token == NULL) + return FALSE; + + * result = x_token; + * index = cur_token; + + return TRUE; +} +*/ + + +LIBETPAN_EXPORT +int mailmime_language_parse(const char * message, size_t length, + size_t * index, + struct mailmime_language ** result) +{ + size_t cur_token; + int r; + int res; + clist * list; + int first; + struct mailmime_language * language; + + cur_token = * index; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + first = TRUE; + + while (1) { + char * atom; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, ','); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto err; + } + + r = mailimf_atom_parse(message, length, &cur_token, &atom); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto err; + } + + r = clist_append(list, atom); + if (r < 0) { + mailimf_atom_free(atom); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + language = mailmime_language_new(list); + if (language == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = language; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimf_atom_free, NULL); + clist_free(list); + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,113 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime.h,v 1.16 2005/06/01 12:22:19 smarinier Exp $ + */ + +#ifndef MAILMIME_H + +#define MAILMIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailimf.h> +#include <libetpan/mailmime_types.h> +#include <libetpan/mailmime_types_helper.h> +#include <libetpan/mailmime_content.h> +#include <libetpan/mailmime_decode.h> +#include <libetpan/mailmime_disposition.h> +#include <libetpan/mailmime_write_file.h> +#include <libetpan/mailmime_write_mem.h> +#include <libetpan/mailmime_write_generic.h> + +LIBETPAN_EXPORT +int mailmime_content_parse(const char * message, size_t length, + size_t * index, + struct mailmime_content ** result); + +LIBETPAN_EXPORT +int mailmime_description_parse(const char * message, size_t length, + size_t * index, + char ** result); + +LIBETPAN_EXPORT +int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result); + +LIBETPAN_EXPORT +int +mailmime_field_parse(struct mailimf_optional_field * field, + struct mailmime_field ** result); + +LIBETPAN_EXPORT +int mailmime_id_parse(const char * message, size_t length, + size_t * index, char ** result); + +LIBETPAN_EXPORT +int +mailmime_fields_parse(struct mailimf_fields * + fields, + struct mailmime_fields ** + result); + +LIBETPAN_EXPORT +int mailmime_version_parse(const char * message, size_t length, + size_t * index, + uint32_t * result); + +LIBETPAN_EXPORT +int +mailmime_extension_token_parse(const char * message, size_t length, + size_t * index, char ** result); + +LIBETPAN_EXPORT +int mailmime_parameter_parse(const char * message, size_t length, + size_t * index, + struct mailmime_parameter ** result); + +LIBETPAN_EXPORT +int mailmime_value_parse(const char * message, size_t length, + size_t * index, char ** result); + +LIBETPAN_EXPORT +int mailmime_language_parse(const char * message, size_t length, + size_t * index, + struct mailmime_language ** result); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_content.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_content.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,2390 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_content.c,v 1.41 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailimf.h" + +#include <string.h> +#include <stdlib.h> + +#include "mailmime.h" +#include "mailmime_types.h" +#include "mmapstring.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/* + RFC 2045 + RFC 2046 + RFC 2047 + + RFC 2231 +*/ + + +static int mailmime_parse_with_default(const char * message, size_t length, + size_t * index, int default_type, + struct mailmime_content * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result); + + + +LIBETPAN_EXPORT +char * mailmime_content_charset_get(struct mailmime_content * content) +{ + char * charset; + + charset = mailmime_content_param_get(content, "charset"); + if (charset == NULL) + return "us-ascii"; + else + return charset; +} + +LIBETPAN_EXPORT +char * mailmime_content_param_get(struct mailmime_content * content, + char * name) +{ + clistiter * cur; + + for(cur = clist_begin(content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + + if (strcasecmp(param->pa_name, name) == 0) + return param->pa_value; + } + + return NULL; +} + + +/* + boundary := 0*69<bchars> bcharsnospace +*/ + +/* + bchars := bcharsnospace / " " +*/ + +/* + bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / + "+" / "_" / "," / "-" / "." / + "/" / ":" / "=" / "?" +*/ + +/* + body-part := <"message" as defined in RFC 822, with all + header fields optional, not starting with the + specified dash-boundary, and with the + delimiter not occurring anywhere in the + body part. Note that the semantics of a + part differ from the semantics of a message, + as described in the text.> +*/ + +/* + close-delimiter := delimiter "--" +*/ + +/* + dash-boundary := "--" boundary + ; boundary taken from the value of + ; boundary parameter of the + ; Content-Type field. +*/ + +/* + delimiter := CRLF dash-boundary +*/ + +/* + discard-text := *(*text CRLF) + ; May be ignored or discarded. +*/ + +/* + encapsulation := delimiter transport-padding + CRLF body-part +*/ + +/* + epilogue := discard-text +*/ + +/* + multipart-body := [preamble CRLF] + dash-boundary transport-padding CRLF + body-part *encapsulation + close-delimiter transport-padding + [CRLF epilogue] +*/ + +/* + preamble := discard-text +*/ + +/* + transport-padding := *LWSP-char + ; Composers MUST NOT generate + ; non-zero length transport + ; padding, but receivers MUST + ; be able to handle padding + ; added by message transports. +*/ + + +/* + ACCESS-TYPE + EXPIRATION + SIZE + PERMISSION +*/ + +/* + 5.2.3.2. The 'ftp' and 'tftp' Access-Types + NAME + SITE + + (3) Before any data are retrieved, using FTP, the user will + generally need to be asked to provide a login id and a + password for the machine named by the site parameter. + For security reasons, such an id and password are not + specified as content-type parameters, but must be + obtained from the user. + + optional : + DIRECTORY + MODE +*/ + +/* +5.2.3.3. The 'anon-ftp' Access-Type +*/ + +/* +5.2.3.4. The 'local-file' Access-Type +NAME +SITE +*/ + +/* +5.2.3.5. The 'mail-server' Access-Type +SERVER +SUBJECT +*/ + + +enum { + PREAMBLE_STATE_A0, + PREAMBLE_STATE_A, + PREAMBLE_STATE_A1, + PREAMBLE_STATE_B, + PREAMBLE_STATE_C, + PREAMBLE_STATE_D, + PREAMBLE_STATE_E +}; + +static int mailmime_preamble_parse(const char * message, size_t length, + size_t * index, int beol) +{ + int state; + size_t cur_token; + + cur_token = * index; + if (beol) + state = PREAMBLE_STATE_A0; + else + state = PREAMBLE_STATE_A; + + while (state != PREAMBLE_STATE_E) { + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (state) { + case PREAMBLE_STATE_A0: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_A1; + break; + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + + case PREAMBLE_STATE_A: + switch (message[cur_token]) { + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + + case PREAMBLE_STATE_A1: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_E; + break; + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + + case PREAMBLE_STATE_B: + switch (message[cur_token]) { + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + case '-': + state = PREAMBLE_STATE_D; + break; + default: + state = PREAMBLE_STATE_A0; + break; + } + break; + + case PREAMBLE_STATE_C: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_D; + break; + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A0; + break; + } + break; + + case PREAMBLE_STATE_D: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_E; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + } + + cur_token ++; + } + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_boundary_parse(const char * message, size_t length, + size_t * index, char * boundary) +{ + size_t cur_token; + size_t len; + + cur_token = * index; + + len = strlen(boundary); + + if (cur_token + len >= length) + return MAILIMF_ERROR_PARSE; + + if (strncmp(message + cur_token, boundary, len) != 0) + return MAILIMF_ERROR_PARSE; + + cur_token += len; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +static int is_wsp(char ch) +{ + if ((ch == ' ') || (ch == '\t')) + return TRUE; + + return FALSE; +} + +static int mailmime_lwsp_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + while (is_wsp(message[cur_token])) { + cur_token ++; + if (cur_token >= length) + break; + } + + if (cur_token == * index) + return MAILIMF_ERROR_PARSE; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +gboolean mailimf_crlf_parse(gchar * message, guint32 length, guint32 * index) +*/ + +enum { + BODY_PART_DASH2_STATE_0, + BODY_PART_DASH2_STATE_1, + BODY_PART_DASH2_STATE_2, + BODY_PART_DASH2_STATE_3, + BODY_PART_DASH2_STATE_4, + BODY_PART_DASH2_STATE_5, + BODY_PART_DASH2_STATE_6 +}; + +static int +mailmime_body_part_dash2_parse(const char * message, size_t length, + size_t * index, char * boundary, + const char ** result, size_t * result_size) +{ + int state; + size_t cur_token; + size_t size; + size_t begin_text; + size_t end_text; + int r; + + cur_token = * index; + state = BODY_PART_DASH2_STATE_0; + + begin_text = cur_token; + end_text = length; + + while (state != BODY_PART_DASH2_STATE_5) { + + if (cur_token >= length) + break; + + switch(state) { + + case BODY_PART_DASH2_STATE_0: + switch (message[cur_token]) { + case '\r': + state = BODY_PART_DASH2_STATE_1; + break; + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_1: + switch (message[cur_token]) { + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_2: + switch (message[cur_token]) { + case '-': + end_text = cur_token; + state = BODY_PART_DASH2_STATE_3; + break; + case '\r': + state = BODY_PART_DASH2_STATE_1; + break; + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_3: + switch (message[cur_token]) { + case '\r': + state = BODY_PART_DASH2_STATE_1; + break; + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + case '-': + state = BODY_PART_DASH2_STATE_4; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_4: + r = mailmime_boundary_parse(message, length, &cur_token, boundary); + if (r == MAILIMF_NO_ERROR) + state = BODY_PART_DASH2_STATE_5; + else + state = BODY_PART_DASH2_STATE_6; + + break; + } + + if ((state != BODY_PART_DASH2_STATE_5) && + (state != BODY_PART_DASH2_STATE_6)) + cur_token ++; + + if (state == BODY_PART_DASH2_STATE_6) + state = BODY_PART_DASH2_STATE_0; + } + + size = end_text - begin_text; + +#if 0 + if (size > 0) { + end_text --; + size --; + } +#endif + + if (size >= 1) { + if (message[end_text - 1] == '\r') { + end_text --; + size --; + } + else if (size >= 1) { + if (message[end_text - 1] == '\n') { + end_text --; + size --; + if (size >= 1) { + if (message[end_text - 1] == '\r') { + end_text --; + size --; + } + } + } + } + } + + size = end_text - begin_text; + if (size == 0) + return MAILIMF_ERROR_PARSE; + +#if 0 + body_part = mailimf_body_new(message + begin_text, size); + if (body_part == NULL) + goto err; +#endif + + * result = message + begin_text; + * result_size = size; + * index = cur_token; + + return MAILIMF_NO_ERROR; +#if 0 + err: + return MAILIMF_ERROR_PARSE; +#endif +} + +static int +mailmime_body_part_dash2_transport_crlf_parse(const char * message, + size_t length, + size_t * index, char * boundary, + const char ** result, size_t * result_size) +{ + size_t cur_token; + int r; + const char * data_str; + size_t data_size; + const char * begin_text; + const char * end_text; + + cur_token = * index; + + begin_text = message + cur_token; + end_text = message + cur_token; + + while (1) { + r = mailmime_body_part_dash2_parse(message, length, &cur_token, + boundary, &data_str, &data_size); + if (r == MAILIMF_NO_ERROR) { + end_text = data_str + data_size; + } + else { + return r; + } + + /* parse transport-padding */ + while (1) { + r = mailmime_lwsp_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + return r; + } + } + + r = mailimf_crlf_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + break; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + return r; + } + } + + * index = cur_token; + * result = begin_text; + * result_size = end_text - begin_text; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_multipart_close_parse(const char * message, size_t length, + size_t * index); + +static int +mailmime_body_part_dash2_close_parse(const char * message, + size_t length, + size_t * index, char * boundary, + const char ** result, size_t * result_size) +{ + size_t cur_token; + int r; + const char * data_str; + size_t data_size; + const char * begin_text; + const char * end_text; + + cur_token = * index; + + begin_text = message + cur_token; + end_text = message + cur_token; + + while (1) { + r = mailmime_body_part_dash2_parse(message, length, + &cur_token, boundary, &data_str, &data_size); + if (r == MAILIMF_NO_ERROR) { + end_text = data_str + data_size; + } + else { + return r; + } + + r = mailmime_multipart_close_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + break; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + return r; + } + } + + * index = cur_token; + * result = data_str; + * result_size = data_size; + + return MAILIMF_NO_ERROR; +} + +enum { + MULTIPART_CLOSE_STATE_0, + MULTIPART_CLOSE_STATE_1, + MULTIPART_CLOSE_STATE_2, + MULTIPART_CLOSE_STATE_3, + MULTIPART_CLOSE_STATE_4 +}; + +static int mailmime_multipart_close_parse(const char * message, size_t length, + size_t * index) +{ + int state; + size_t cur_token; + + cur_token = * index; + state = MULTIPART_CLOSE_STATE_0; + + while (state != MULTIPART_CLOSE_STATE_4) { + + switch(state) { + + case MULTIPART_CLOSE_STATE_0: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (message[cur_token]) { + case '-': + state = MULTIPART_CLOSE_STATE_1; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + + case MULTIPART_CLOSE_STATE_1: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (message[cur_token]) { + case '-': + state = MULTIPART_CLOSE_STATE_2; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + + case MULTIPART_CLOSE_STATE_2: + if (cur_token >= length) { + state = MULTIPART_CLOSE_STATE_4; + break; + } + + switch (message[cur_token]) { + case ' ': + state = MULTIPART_CLOSE_STATE_2; + break; + case '\t': + state = MULTIPART_CLOSE_STATE_2; + break; + case '\r': + state = MULTIPART_CLOSE_STATE_3; + break; + case '\n': + state = MULTIPART_CLOSE_STATE_4; + break; + default: + state = MULTIPART_CLOSE_STATE_4; + break; + } + break; + + case MULTIPART_CLOSE_STATE_3: + if (cur_token >= length) { + state = MULTIPART_CLOSE_STATE_4; + break; + } + + switch (message[cur_token]) { + case '\n': + state = MULTIPART_CLOSE_STATE_4; + break; + default: + state = MULTIPART_CLOSE_STATE_4; + break; + } + break; + } + + cur_token ++; + } + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +enum { + MULTIPART_NEXT_STATE_0, + MULTIPART_NEXT_STATE_1, + MULTIPART_NEXT_STATE_2 +}; + +LIBETPAN_EXPORT +int mailmime_multipart_next_parse(const char * message, size_t length, + size_t * index) +{ + int state; + size_t cur_token; + + cur_token = * index; + state = MULTIPART_NEXT_STATE_0; + + while (state != MULTIPART_NEXT_STATE_2) { + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(state) { + + case MULTIPART_NEXT_STATE_0: + switch (message[cur_token]) { + case ' ': + state = MULTIPART_NEXT_STATE_0; + break; + case '\t': + state = MULTIPART_NEXT_STATE_0; + break; + case '\r': + state = MULTIPART_NEXT_STATE_1; + break; + case '\n': + state = MULTIPART_NEXT_STATE_2; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + + case MULTIPART_NEXT_STATE_1: + switch (message[cur_token]) { + case '\n': + state = MULTIPART_NEXT_STATE_2; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + } + + cur_token ++; + } + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_multipart_body_parse(const char * message, size_t length, + size_t * index, char * boundary, + int default_subtype, + clist ** result, + struct mailmime_data ** p_preamble, + struct mailmime_data ** p_epilogue) +{ + size_t cur_token; + clist * list; + int r; + int res; +#if 0 + size_t begin; +#endif + size_t preamble_begin; + size_t preamble_length; + size_t preamble_end; +#if 0 + int no_preamble; + size_t before_crlf; +#endif + size_t epilogue_begin; + size_t epilogue_length; + struct mailmime_data * preamble; + struct mailmime_data * epilogue; + size_t part_begin; + int final_part; + + preamble = NULL; + epilogue = NULL; + + cur_token = * index; + preamble_begin = cur_token; + +#if 0 + no_preamble = FALSE; +#endif + preamble_end = preamble_begin; + +#if 0 + r = mailmime_preamble_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ +#if 0 + preamble_end = cur_token - 2; +#endif + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + no_preamble = TRUE; + } + else { + res = r; + goto err; + } + + while (1) { + + preamble_end = cur_token; + r = mailmime_boundary_parse(message, length, &cur_token, boundary); + if (r == MAILIMF_NO_ERROR) { + break; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + + r = mailmime_preamble_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { +#if 0 + preamble_end = cur_token - 2; +#endif + } + else if (r == MAILIMF_ERROR_PARSE) { + no_preamble = TRUE; + break; + } + else { + res = r; + goto err; + } + } + + if (no_preamble) { +#if 0 + preamble_end = cur_token; +#endif + } + else { + + r = mailmime_lwsp_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + before_crlf = cur_token; + r = mailimf_crlf_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { +#if 0 + preamble_end = before_crlf; +#endif + /* remove the CR LF at the end of preamble if any */ + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + } + preamble_length = preamble_end - begin; +#endif + + r = mailmime_preamble_parse(message, length, &cur_token, 1); + if (r == MAILIMF_NO_ERROR) { + while (1) { + + preamble_end = cur_token; + r = mailmime_boundary_parse(message, length, &cur_token, boundary); + if (r == MAILIMF_NO_ERROR) { + break; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + + r = mailmime_preamble_parse(message, length, &cur_token, 0); + if (r == MAILIMF_NO_ERROR) { + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto err; + } + } + } + + preamble_end -= 2; + if (preamble_end != preamble_begin) { + /* try to find the real end of the preamble (strip CR LF) */ + if (message[preamble_end - 1] == '\n') { + preamble_end --; + if (preamble_end - 1 >= preamble_begin) { + if (message[preamble_end - 1] == '\r') + preamble_end --; + } + } + else if (message[preamble_end - 1] == '\r') { + preamble_end --; + } + } + preamble_length = preamble_end - preamble_begin; + + part_begin = cur_token; + while (1) { + r = mailmime_lwsp_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } +#if 0 + if (r == MAILIMF_ERROR_PARSE) + break; +#endif + + r = mailimf_crlf_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + part_begin = cur_token; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + break; + } + else { + res = r; + goto err; + } + } + + cur_token = part_begin; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + final_part = 0; + + while (!final_part) { + size_t bp_token; + struct mailmime * mime_bp; + const char * data_str; + size_t data_size; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + +#if 0 + int got_crlf; + size_t after_boundary; + + /* XXX - begin */ + r = mailmime_body_part_dash2_parse(message, length, &cur_token, + boundary, &data_str, &data_size); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto free; + } + + after_boundary = cur_token; + got_crlf = 0; + /* parse transport-padding */ + while (1) { + r = mailmime_lwsp_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } + + r = mailimf_crlf_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + got_crlf = 1; + break; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + break; + } + else { + res = r; + goto free; + } + } + if (after_boundary != cur_token) { + if (!got_crlf) { + r = mailimf_crlf_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + got_crlf = 1; + break; + } + } + } + /* XXX - end */ +#endif + + r = mailmime_body_part_dash2_transport_crlf_parse(message, length, + &cur_token, boundary, &data_str, &data_size); + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_body_part_dash2_close_parse(message, length, + &cur_token, boundary, &data_str, &data_size); + if (r == MAILIMF_NO_ERROR) { + final_part = 1; + } + } + + if (r == MAILIMF_NO_ERROR) { + bp_token = 0; + + r = mailimf_optional_fields_parse(data_str, data_size, + &bp_token, &fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } + + r = mailimf_crlf_parse(data_str, data_size, &bp_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + mailimf_fields_free(fields); + res = r; + goto free; + } + + mime_fields = NULL; + r = mailmime_fields_parse(fields, &mime_fields); + mailimf_fields_free(fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } + + r = mailmime_parse_with_default(data_str, data_size, + &bp_token, default_subtype, NULL, + mime_fields, &mime_bp); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, mime_bp); + if (r < 0) { + mailmime_free(mime_bp); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + else if (r == MAILIMF_ERROR_PARSE) { + mailmime_fields_free(mime_fields); + break; + } + else { + mailmime_fields_free(mime_fields); + res = r; + goto free; + } + + r = mailmime_multipart_next_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + } + else { + res = r; + goto free; + } + +#if 0 + else if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_body_part_dash2_parse(message, length, + &cur_token, boundary, &data_str, &data_size); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + + r = mailmime_multipart_close_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + break; + } + else if (r == MAILIMF_ERROR_PARSE) { + res = r; + goto free; +#if 0 + fprintf(stderr, "close not found, reparse %s\n", boundary); + /* reparse */ + continue; +#endif + } + else { + res = r; + goto free; + } + } + else { + res = r; + goto free; + } +#endif + } + + epilogue_begin = length; + /* parse transport-padding */ + while (1) { + r = mailmime_lwsp_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } + + if (r == MAILIMF_ERROR_PARSE) + break; + +#if 0 + if (r == MAILIMF_ERROR_PARSE) + break; +#endif + +#if 0 + before_crlf = cur_token; +#endif + } + + r = mailimf_crlf_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + epilogue_begin = cur_token; + } + else if (r != MAILIMF_ERROR_PARSE) { + res = r; + goto free; + } + + /* add preamble and epilogue */ + + epilogue_length = length - epilogue_begin; + + if (preamble_length != 0) { + preamble = mailmime_data_new(MAILMIME_DATA_TEXT, + MAILMIME_MECHANISM_8BIT, 1, + message + preamble_begin, preamble_length, + NULL); + if (preamble == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + if (epilogue_length != 0) { + epilogue = mailmime_data_new(MAILMIME_DATA_TEXT, + MAILMIME_MECHANISM_8BIT, 1, + message + epilogue_begin, epilogue_length, + NULL); + if (epilogue == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + /* end of preamble and epilogue */ + + cur_token = length; + + * result = list; + * p_preamble = preamble; + * p_epilogue = epilogue; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (epilogue != NULL) + mailmime_data_free(epilogue); + if (preamble != NULL) + mailmime_data_free(preamble); + clist_foreach(list, (clist_func) mailmime_free, NULL); + clist_free(list); + err: + return res; +} + +enum { + MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, + MAILMIME_DEFAULT_TYPE_MESSAGE +}; + + +LIBETPAN_EXPORT +int mailmime_parse(const char * message, size_t length, + size_t * index, struct mailmime ** result) +{ + struct mailmime * mime; + int r; + int res; + struct mailmime_content * content_message; + size_t cur_token; + struct mailmime_fields * mime_fields; + const char * data_str; + size_t data_size; + size_t bp_token; + + cur_token = * index; + + content_message = mailmime_get_content_message(); + if (content_message == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + mime_fields = mailmime_fields_new_with_data(content_message, + NULL, + NULL, + NULL, + NULL, + NULL); + if (mime_fields == NULL) { + mailmime_content_free(content_message); + res = MAILIMF_ERROR_MEMORY; + goto err; + } +#endif + mime_fields = mailmime_fields_new_empty(); + if (mime_fields == NULL) { + mailmime_content_free(content_message); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + data_str = message + cur_token; + data_size = length - cur_token; + + bp_token = 0; + r = mailmime_parse_with_default(data_str, data_size, + &bp_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, + content_message, mime_fields, &mime); + cur_token += bp_token; + if (r != MAILIMF_NO_ERROR) { + mailmime_fields_free(mime_fields); + res = r; + goto free; + } + + * index = cur_token; + * result = mime; + + return MAILIMF_NO_ERROR; + + free: + mailmime_fields_free(mime_fields); + err: + return res; +} + + +LIBETPAN_EXPORT +char * mailmime_extract_boundary(struct mailmime_content * content_type) +{ + char * boundary; + + boundary = mailmime_content_param_get(content_type, "boundary"); + + if (boundary != NULL) { + int len; + char * new_boundary; + + len = strlen(boundary); + new_boundary = malloc(len + 1); + if (new_boundary == NULL) + return NULL; + + if (boundary[0] == '"') { + strncpy(new_boundary, boundary + 1, len - 2); + new_boundary[len - 2] = 0; + } + else + strcpy(new_boundary, boundary); + + boundary = new_boundary; + } + + return boundary; +} + +static void remove_unparsed_mime_headers(struct mailimf_fields * fields) +{ + clistiter * cur; + + cur = clist_begin(fields->fld_list); + while (cur != NULL) { + struct mailimf_field * field; + int delete; + + field = clist_content(cur); + + switch (field->fld_type) { + case MAILIMF_FIELD_OPTIONAL_FIELD: + delete = 0; + if (strncasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-", 8) == 0) { + char * name; + + name = field->fld_data.fld_optional_field->fld_name + 8; + if ((strcasecmp(name, "Type") == 0) + || (strcasecmp(name, "Transfer-Encoding") == 0) + || (strcasecmp(name, "ID") == 0) + || (strcasecmp(name, "Description") == 0) + || (strcasecmp(name, "Disposition") == 0) + || (strcasecmp(name, "Language") == 0)) { + delete = 1; + } + } + else if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "MIME-Version") == 0) { + delete = 1; + } + + if (delete) { + cur = clist_delete(fields->fld_list, cur); + mailimf_field_free(field); + } + else { + cur = clist_next(cur); + } + break; + + default: + cur = clist_next(cur); + } + } +} + +static int mailmime_parse_with_default(const char * message, size_t length, + size_t * index, int default_type, + struct mailmime_content * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result) +{ + size_t cur_token; + + int body_type; + + int encoding; + struct mailmime_data * body; + char * boundary; + struct mailimf_fields * fields; + clist * list; + struct mailmime * msg_mime; + + struct mailmime * mime; + + int r; + int res; + struct mailmime_data * preamble; + struct mailmime_data * epilogue; + + /* + note that when this function is called, content type is always detached, + even if the function fails + */ + + preamble = NULL; + epilogue = NULL; + + cur_token = * index; + + /* get content type */ + + if (content_type == NULL) { + if (mime_fields != NULL) { + clistiter * cur; + + for(cur = clist_begin(mime_fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TYPE) { + content_type = field->fld_data.fld_content; + + /* detach content type from list */ + field->fld_data.fld_content = NULL; + clist_delete(mime_fields->fld_list, cur); + mailmime_field_free(field); + /* + there may be a leak due to the detached content type + in case the function fails + */ + break; + } + } + } + } + + /* set default type if no content type */ + + if (content_type == NULL) { + /* content_type is detached, in any case, we will have to free it */ + if (default_type == MAILMIME_DEFAULT_TYPE_TEXT_PLAIN) { + content_type = mailmime_get_content_text(); + if (content_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + } + else /* message */ { + body_type = MAILMIME_MESSAGE; + + content_type = mailmime_get_content_message(); + if (content_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + } + } + + /* get the body type */ + + boundary = NULL; /* XXX - removes a gcc warning */ + + switch (content_type->ct_type->tp_type) { + case MAILMIME_TYPE_COMPOSITE_TYPE: + switch (content_type->ct_type->tp_data.tp_composite_type->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + boundary = mailmime_extract_boundary(content_type); + + if (boundary == NULL) + body_type = MAILMIME_SINGLE; + else + body_type = MAILMIME_MULTIPLE; + break; + + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + + if (strcasecmp(content_type->ct_subtype, "rfc822") == 0) + body_type = MAILMIME_MESSAGE; + else + body_type = MAILMIME_SINGLE; + break; + + default: + res = MAILIMF_ERROR_INVAL; + goto free_content; + } + break; + + default: /* MAILMIME_TYPE_DISCRETE_TYPE */ + body_type = MAILMIME_SINGLE; + break; + } + + /* set body */ + + if (mime_fields != NULL) + encoding = mailmime_transfer_encoding_get(mime_fields); + else + encoding = MAILMIME_MECHANISM_8BIT; + + cur_token = * index; + body = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, 1, + message + cur_token, length - cur_token, + NULL); + if (body == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_content; + } + + /* in case of composite, parse the sub-part(s) */ + + list = NULL; + msg_mime = NULL; + fields = NULL; + + switch (body_type) { + case MAILMIME_MESSAGE: + { + struct mailmime_fields * submime_fields; + + r = mailimf_envelope_and_optional_fields_parse(message, length, + &cur_token, &fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_content; + } + + r = mailimf_crlf_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + mailimf_fields_free(fields); + res = r; + goto free_content; + } + + submime_fields = NULL; + r = mailmime_fields_parse(fields, &submime_fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + mailimf_fields_free(fields); + res = r; + goto free_content; + } + + remove_unparsed_mime_headers(fields); + + r = mailmime_parse_with_default(message, length, + &cur_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, + NULL, submime_fields, &msg_mime); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + mailmime_fields_free(mime_fields); + msg_mime = NULL; + } + else { + mailmime_fields_free(mime_fields); + res = r; + goto free_content; + } + } + + break; + + case MAILMIME_MULTIPLE: + { + int default_subtype; + + default_subtype = MAILMIME_DEFAULT_TYPE_TEXT_PLAIN; + if (content_type != NULL) + if (strcasecmp(content_type->ct_subtype, "digest") == 0) + default_subtype = MAILMIME_DEFAULT_TYPE_MESSAGE; + + cur_token = * index; + r = mailmime_multipart_body_parse(message, length, + &cur_token, boundary, + default_subtype, + &list, &preamble, &epilogue); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_content; + } + } + else { + res = r; + goto free_content; + } + + free(boundary); + } + break; + + default: /* MAILMIME_SINGLE */ + /* do nothing */ + break; + } + + mime = mailmime_new(body_type, message, length, + mime_fields, content_type, + body, preamble, /* preamble */ + epilogue, /* epilogue */ + list, fields, msg_mime); + if (mime == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mime; + * index = length; + + return MAILIMF_NO_ERROR; + + free: + if (epilogue != NULL) + mailmime_data_free(epilogue); + if (preamble != NULL) + mailmime_data_free(preamble); + if (msg_mime != NULL) + mailmime_free(msg_mime); + if (list != NULL) { + clist_foreach(list, (clist_func) mailmime_free, NULL); + clist_free(list); + } + free_content: + mailmime_content_free(content_type); + err: + return res; +} + +static int mailmime_get_section_list(struct mailmime * mime, + clistiter * list, struct mailmime ** result) +{ + uint32_t id; + struct mailmime * data; + struct mailmime * submime; + + if (list == NULL) { + * result = mime; + return MAILIMF_NO_ERROR; + } + + id = * ((uint32_t *) clist_content(list)); + + data = NULL; + switch (mime->mm_type) { + case MAILMIME_SINGLE: + return MAILIMF_ERROR_INVAL; + + case MAILMIME_MULTIPLE: + data = clist_nth_data(mime->mm_data.mm_multipart.mm_mp_list, id - 1); + if (data == NULL) + return MAILIMF_ERROR_INVAL; + + if (clist_next(list) != NULL) + return mailmime_get_section_list(data, clist_next(list), result); + else { + * result = data; + return MAILIMF_NO_ERROR; + } + + case MAILMIME_MESSAGE: + submime = mime->mm_data.mm_message.mm_msg_mime; + switch (submime->mm_type) { + case MAILMIME_MULTIPLE: + data = clist_nth_data(submime->mm_data.mm_multipart.mm_mp_list, id - 1); + if (data == NULL) + return MAILIMF_ERROR_INVAL; + return mailmime_get_section_list(data, clist_next(list), result); + + default: + if (id != 1) + return MAILIMF_ERROR_INVAL; + + data = submime; + if (data == NULL) + return MAILIMF_ERROR_INVAL; + + return mailmime_get_section_list(data, clist_next(list), result); + } + break; + + default: + return MAILIMF_ERROR_INVAL; + } +} + +LIBETPAN_EXPORT +int mailmime_get_section(struct mailmime * mime, + struct mailmime_section * section, + struct mailmime ** result) +{ + return mailmime_get_section_list(mime, + clist_begin(section->sec_list), result); +} + + + + + + + + + + + + + + + +/* ************************************************************************* */ +/* MIME part decoding */ + +static inline signed char get_base64_value(char ch) +{ + if ((ch >= 'A') && (ch <= 'Z')) + return ch - 'A'; + if ((ch >= 'a') && (ch <= 'z')) + return ch - 'a' + 26; + if ((ch >= '0') && (ch <= '9')) + return ch - '0' + 52; + switch (ch) { + case '+': + return 62; + case '/': + return 63; + case '=': /* base64 padding */ + return -1; + default: + return -1; + } +} + +int mailmime_base64_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len) +{ + size_t cur_token; + size_t i; + char chunk[4]; + int chunk_index; + char out[3]; + MMAPString * mmapstr; + int res; + int r; + size_t written; + + cur_token = * index; + chunk_index = 0; + written = 0; + + mmapstr = mmap_string_sized_new((length - cur_token) * 3 / 4); + if (mmapstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + i = 0; + while (1) { + signed char value; + + value = -1; + while (value == -1) { + + if (cur_token >= length) + break; + + value = get_base64_value(message[cur_token]); + cur_token ++; + } + + if (value == -1) + break; + + chunk[chunk_index] = value; + chunk_index ++; + + if (chunk_index == 4) { + out[0] = (chunk[0] << 2) | (chunk[1] >> 4); + out[1] = (chunk[1] << 4) | (chunk[2] >> 2); + out[2] = (chunk[2] << 6) | (chunk[3]); + + chunk[0] = 0; + chunk[1] = 0; + chunk[2] = 0; + chunk[3] = 0; + + chunk_index = 0; + + if (mmap_string_append_len(mmapstr, out, 3) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + written += 3; + } + } + + if (chunk_index != 0) { + size_t len; + + len = 0; + out[0] = (chunk[0] << 2) | (chunk[1] >> 4); + len ++; + + if (chunk_index >= 3) { + out[1] = (chunk[1] << 4) | (chunk[2] >> 2); + len ++; + } + + if (mmap_string_append_len(mmapstr, out, len) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + written += len; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = mmapstr->str; + * result_len = written; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(mmapstr); + err: + return res; +} + + + +static inline int hexa_to_char(char hexdigit) +{ + if ((hexdigit >= '0') && (hexdigit <= '9')) + return hexdigit - '0'; + if ((hexdigit >= 'a') && (hexdigit <= 'f')) + return hexdigit - 'a' + 10; + if ((hexdigit >= 'A') && (hexdigit <= 'F')) + return hexdigit - 'A' + 10; + return 0; +} + +static inline char to_char(const char * hexa) +{ + return (hexa_to_char(hexa[0]) << 4) | hexa_to_char(hexa[1]); +} + +enum { + STATE_NORMAL, + STATE_CODED, + STATE_OUT, + STATE_CR +}; + + +static int write_decoded_qp(MMAPString * mmapstr, + const char * start, size_t count) +{ + if (mmap_string_append_len(mmapstr, start, count) == NULL) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + + +#define WRITE_MAX_QP 512 + +int mailmime_quoted_printable_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len, int in_header) +{ + size_t cur_token; + int state; + int r; + char ch; + size_t count; + const char * start; + MMAPString * mmapstr; + int res; + size_t written; + + state = STATE_NORMAL; + cur_token = * index; + + count = 0; + start = message + cur_token; + written = 0; + + mmapstr = mmap_string_sized_new(length - cur_token); + if (mmapstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + if (length >= 1) { + if (message[length - 1] == '\n') { + length --; + if (length >= 1) + if (message[length - 1] == '\r') { + length --; + } + } + } +#endif + + while (state != STATE_OUT) { + + if (cur_token >= length) { + state = STATE_OUT; + break; + } + + switch (state) { + + case STATE_CODED: + + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + switch (message[cur_token]) { + case '=': + if (cur_token + 1 >= length) { + /* error but ignore it */ + state = STATE_NORMAL; + start = message + cur_token; + cur_token ++; + count ++; + break; + } + + switch (message[cur_token + 1]) { + + case '\n': + cur_token += 2; + + start = message + cur_token; + + state = STATE_NORMAL; + break; + + case '\r': + if (cur_token + 2 >= length) { + state = STATE_OUT; + break; + } + + if (message[cur_token + 2] == '\n') + cur_token += 3; + else + cur_token += 2; + + start = message + cur_token; + + state = STATE_NORMAL; + + break; + + default: + if (cur_token + 2 >= length) { + /* error but ignore it */ + cur_token ++; + + start = message + cur_token; + + count ++; + state = STATE_NORMAL; + break; + } + +#if 0 + /* flush before writing additionnal information */ + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; +#endif + + ch = to_char(message + cur_token + 1); + + if (mmap_string_append_c(mmapstr, ch) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + cur_token += 3; + written ++; + + start = message + cur_token; + + state = STATE_NORMAL; + break; + } + break; + } + break; /* end of STATE_ENCODED */ + + case STATE_NORMAL: + + switch (message[cur_token]) { + + case '=': + state = STATE_CODED; + break; + + case '\n': + /* flush before writing additionnal information */ + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + + count = 0; + } + + r = write_decoded_qp(mmapstr, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += 2; + cur_token ++; + start = message + cur_token; + break; + + case '\r': + state = STATE_CR; + cur_token ++; + break; + + case '_': + if (in_header) { + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + if (mmap_string_append_c(mmapstr, ' ') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + written ++; + cur_token ++; + start = message + cur_token; + + break; + } + /* WARINING : must be followed by switch default action */ + + default: + if (count >= WRITE_MAX_QP) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + start = message + cur_token; + } + + count ++; + cur_token ++; + break; + } + break; /* end of STATE_NORMAL */ + + case STATE_CR: + switch (message[cur_token]) { + + case '\n': + /* flush before writing additionnal information */ + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + r = write_decoded_qp(mmapstr, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += 2; + cur_token ++; + start = message + cur_token; + state = STATE_NORMAL; + break; + + default: + /* flush before writing additionnal information */ + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + start = message + cur_token; + + r = write_decoded_qp(mmapstr, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += 2; + state = STATE_NORMAL; + } + break; /* end of STATE_CR */ + } + } + + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = mmapstr->str; + * result_len = written; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(mmapstr); + err: + return res; +} + +int mailmime_binary_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + if (length >= 1) { + if (message[length - 1] == '\n') { + length --; + if (length >= 1) + if (message[length - 1] == '\r') + length --; + } + } + + mmapstr = mmap_string_new_len(message + cur_token, length - cur_token); + if (mmapstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * index = length; + * result = mmapstr->str; + * result_len = length - cur_token; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(mmapstr); + err: + return res; +} + + +int mailmime_part_parse(const char * message, size_t length, + size_t * index, + int encoding, char ** result, size_t * result_len) +{ + switch (encoding) { + case MAILMIME_MECHANISM_BASE64: + return mailmime_base64_body_parse(message, length, index, + result, result_len); + + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + return mailmime_quoted_printable_body_parse(message, length, index, + result, result_len, FALSE); + + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_BINARY: + default: + return mailmime_binary_body_parse(message, length, index, + result, result_len); + } +} + +int mailmime_get_section_id(struct mailmime * mime, + struct mailmime_section ** result) +{ + clist * list; + int res; + struct mailmime_section * section_id; + int r; + + if (mime->mm_parent == NULL) { + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + section_id = mailmime_section_new(list); + if (section_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + } + else { + uint32_t id; + uint32_t * p_id; + clistiter * cur; + struct mailmime * parent; + + r = mailmime_get_section_id(mime->mm_parent, §ion_id); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + parent = mime->mm_parent; + switch (parent->mm_type) { + case MAILMIME_MULTIPLE: + id = 1; + for(cur = clist_begin(parent->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + if (clist_content(cur) == mime) + break; + id ++; + } + + p_id = malloc(sizeof(* p_id)); + if (p_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + * p_id = id; + + r = clist_append(section_id->sec_list, p_id); + if (r < 0) { + free(p_id); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + break; + + case MAILMIME_MESSAGE: + if ((mime->mm_type == MAILMIME_SINGLE) || + (mime->mm_type == MAILMIME_MESSAGE)) { + p_id = malloc(sizeof(* p_id)); + if (p_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + * p_id = 1; + + r = clist_append(section_id->sec_list, p_id); + if (r < 0) { + free(p_id); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + } + } + + * result = section_id; + + return MAILIMF_NO_ERROR; + + free: + mailmime_section_free(section_id); + err: + return res; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_content.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_content.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,99 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_content.h,v 1.15 2005/06/01 12:22:19 smarinier Exp $ + */ + +#ifndef MAILMIME_CONTENT_H + +#define MAILMIME_CONTENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailmime_types.h> + +LIBETPAN_EXPORT +char * mailmime_content_charset_get(struct mailmime_content * content); + +LIBETPAN_EXPORT +char * mailmime_content_param_get(struct mailmime_content * content, + char * name); + +LIBETPAN_EXPORT +int mailmime_parse(const char * message, size_t length, + size_t * index, struct mailmime ** result); + +LIBETPAN_EXPORT +int mailmime_get_section(struct mailmime * mime, + struct mailmime_section * section, + struct mailmime ** result); + + +LIBETPAN_EXPORT +char * mailmime_extract_boundary(struct mailmime_content * content_type); + + +/* decode */ + +LIBETPAN_EXPORT +int mailmime_base64_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailmime_quoted_printable_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len, int in_header); + + +LIBETPAN_EXPORT +int mailmime_binary_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + +LIBETPAN_EXPORT +int mailmime_part_parse(const char * message, size_t length, + size_t * index, + int encoding, char ** result, size_t * result_len); + + +LIBETPAN_EXPORT +int mailmime_get_section_id(struct mailmime * mime, + struct mailmime_section ** result); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_decode.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_decode.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,571 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_decode.c,v 1.30 2006/10/07 17:04:18 hoa Exp $ + */ + +/* + RFC 2047 : MIME (Multipurpose Internet Mail Extensions) Part Three: + Message Header Extensions for Non-ASCII Text +*/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmime_decode.h" + +#include <ctype.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif +#include <string.h> +#include <stdlib.h> + +#include "mailmime_content.h" + +#include "charconv.h" +#include "mmapstring.h" +#include "mailimf.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +static int mailmime_charset_parse(const char * message, size_t length, + size_t * index, char ** charset); + +enum { + MAILMIME_ENCODING_B, + MAILMIME_ENCODING_Q +}; + +static int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailmime_etoken_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int +mailmime_non_encoded_word_parse(const char * message, size_t length, + size_t * index, + char ** result); + +static int +mailmime_encoded_word_parse(const char * message, size_t length, + size_t * index, + struct mailmime_encoded_word ** result); + + +enum { + TYPE_ERROR, + TYPE_WORD, + TYPE_ENCODED_WORD +}; + +LIBETPAN_EXPORT +int mailmime_encoded_phrase_parse(const char * default_fromcode, + const char * message, size_t length, + size_t * index, const char * tocode, + char ** result) +{ + MMAPString * gphrase; + struct mailmime_encoded_word * word; + int first; + size_t cur_token; + int r; + int res; + char * str; + char * wordutf8; + int type; + + cur_token = * index; + + gphrase = mmap_string_new(""); + if (gphrase == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + first = TRUE; + + type = TYPE_ERROR; /* XXX - removes a gcc warning */ + + while (1) { + + word = NULL; + r = mailmime_encoded_word_parse(message, length, &cur_token, &word); + if (r == MAILIMF_NO_ERROR) { + if (!first) { + if (type != TYPE_ENCODED_WORD) { + if (mmap_string_append_c(gphrase, ' ') == NULL) { + mailmime_encoded_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + } + type = TYPE_ENCODED_WORD; + wordutf8 = NULL; + if (strcasecmp(word->wd_charset, "unknown") == 0) { + r = charconv(tocode, "iso-8859-1", word->wd_text, + strlen(word->wd_text), &wordutf8); + } + else { + r = charconv(tocode, word->wd_charset, word->wd_text, + strlen(word->wd_text), &wordutf8); + } + switch (r) { + case MAIL_CHARCONV_ERROR_MEMORY: + mailmime_encoded_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + + case MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET: + case MAIL_CHARCONV_ERROR_CONV: + mailmime_encoded_word_free(word); + res = MAILIMF_ERROR_PARSE; + goto free; + } + + if (wordutf8 != NULL) { + if (mmap_string_append(gphrase, wordutf8) == NULL) { + mailmime_encoded_word_free(word); + free(wordutf8); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + free(wordutf8); + } + mailmime_encoded_word_free(word); + first = FALSE; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free; + } + + if (r == MAILIMF_ERROR_PARSE) { + char * raw_word; + + raw_word = NULL; + r = mailmime_non_encoded_word_parse(message, length, + &cur_token, &raw_word); + if (r == MAILIMF_NO_ERROR) { + if (!first) { + if (mmap_string_append_c(gphrase, ' ') == NULL) { + free(raw_word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + type = TYPE_WORD; + + wordutf8 = NULL; + r = charconv(tocode, default_fromcode, raw_word, + strlen(raw_word), &wordutf8); + + switch (r) { + case MAIL_CHARCONV_ERROR_MEMORY: + free(raw_word); + res = MAILIMF_ERROR_MEMORY; + goto free; + + case MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET: + case MAIL_CHARCONV_ERROR_CONV: + free(raw_word); + res = MAILIMF_ERROR_PARSE; + goto free; + } + + if (mmap_string_append(gphrase, wordutf8) == NULL) { + free(wordutf8); + free(raw_word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + free(wordutf8); + free(raw_word); + first = FALSE; + } + else if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_fws_parse(message, length, &cur_token); + if (r != MAILIMF_NO_ERROR) { + break; + } + + if (mmap_string_append_c(gphrase, ' ') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + first = FALSE; + break; + } + else { + res = r; + goto free; + } + } + } + + if (first) { + res = MAILIMF_ERROR_PARSE; + goto free; + } + + str = strdup(gphrase->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + mmap_string_free(gphrase); + + * result = str; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(gphrase); + err: + return res; +} + +static int +mailmime_non_encoded_word_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + int end; + size_t cur_token; + int res; + char * text; + int r; + size_t begin; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + begin = cur_token; + + end = FALSE; + while (1) { + if (cur_token >= length) + break; + + switch (message[cur_token]) { + case ' ': + case '\t': + case '\r': + case '\n': + end = TRUE; + break; + } + + if (end) + break; + + cur_token ++; + } + + if (cur_token - begin == 0) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + text = malloc(cur_token - begin + 1); + if (text == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + memcpy(text, message + begin, cur_token - begin); + text[cur_token - begin] = '\0'; + + * index = cur_token; + * result = text; + + return MAILIMF_NO_ERROR; + + err: + return res; +} + +static int mailmime_encoded_word_parse(const char * message, size_t length, + size_t * index, + struct mailmime_encoded_word ** result) +{ + size_t cur_token; + char * charset; + int encoding; + char * text; + size_t end_encoding; + char * decoded; + size_t decoded_len; + struct mailmime_encoded_word * ew; + int r; + int res; + int opening_quote; + int end; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + opening_quote = FALSE; + r = mailimf_char_parse(message, length, &cur_token, '\"'); + if (r == MAILIMF_NO_ERROR) { + opening_quote = TRUE; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + + r = mailimf_token_case_insensitive_parse(message, length, &cur_token, "=?"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailmime_charset_parse(message, length, &cur_token, &charset); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_char_parse(message, length, &cur_token, '?'); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + + r = mailmime_encoding_parse(message, length, &cur_token, &encoding); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + + r = mailimf_char_parse(message, length, &cur_token, '?'); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + + end = FALSE; + end_encoding = cur_token; + while (1) { + if (end_encoding >= length) + break; + + switch (message[end_encoding]) { + case '?': +#if 0 + case ' ': +#endif + end = TRUE; + break; + } + + if (end) + break; + + end_encoding ++; + } + + decoded_len = 0; + decoded = NULL; + switch (encoding) { + case MAILMIME_ENCODING_B: + r = mailmime_base64_body_parse(message, end_encoding, + &cur_token, &decoded, + &decoded_len); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + break; + case MAILMIME_ENCODING_Q: + r = mailmime_quoted_printable_body_parse(message, end_encoding, + &cur_token, &decoded, + &decoded_len, TRUE); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + + break; + } + + text = malloc(decoded_len + 1); + if (text == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_charset; + } + + if (decoded_len > 0) + memcpy(text, decoded, decoded_len); + text[decoded_len] = '\0'; + + mailmime_decoded_part_free(decoded); + + r = mailimf_token_case_insensitive_parse(message, length, &cur_token, "?="); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_encoded_text; + } + + if (opening_quote) { + r = mailimf_char_parse(message, length, &cur_token, '\"'); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_encoded_text; + } + } + + ew = mailmime_encoded_word_new(charset, text); + if (ew == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_encoded_text; + } + + * result = ew; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_encoded_text: + mailmime_encoded_text_free(text); + free_charset: + mailmime_charset_free(charset); + err: + return res; +} + +static int mailmime_charset_parse(const char * message, size_t length, + size_t * index, char ** charset) +{ + return mailmime_etoken_parse(message, length, index, charset); +} + +static int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + int encoding; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch ((char) toupper((unsigned char) message[cur_token])) { + case 'Q': + encoding = MAILMIME_ENCODING_Q; + break; + case 'B': + encoding = MAILMIME_ENCODING_B; + break; + default: + return MAILIMF_ERROR_INVAL; + } + + cur_token ++; + + * result = encoding; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +int is_etoken_char(char ch) +{ + unsigned char uch = ch; + + if (uch < 31) + return FALSE; + + switch (uch) { + case ' ': + case '(': + case ')': + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '"': + case '/': + case '[': + case ']': + case '?': + case '.': + case '=': + return FALSE; + } + + return TRUE; +} + +static int mailmime_etoken_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_custom_string_parse(message, length, + index, result, + is_etoken_char); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_decode.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_decode.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_decode.h,v 1.13 2005/06/01 12:22:19 smarinier Exp $ + */ + +#ifndef MAILMIME_DECODE_H + +#define MAILMIME_DECODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailmime_types.h> + +LIBETPAN_EXPORT +int mailmime_encoded_phrase_parse(const char * default_fromcode, + const char * message, size_t length, + size_t * index, const char * tocode, + char ** result); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_disposition.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_disposition.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,600 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_disposition.c,v 1.13 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmime_disposition.h" +#include "mailmime.h" + +#include <ctype.h> +#include <stdlib.h> + +static int +mailmime_disposition_parm_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_parm ** + result); + +static int +mailmime_creation_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int +mailmime_filename_parm_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int +mailmime_modification_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int +mailmime_read_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int +mailmime_size_parm_parse(const char * message, size_t length, + size_t * index, size_t * result); + +static int +mailmime_quoted_date_time_parse(const char * message, size_t length, + size_t * index, char ** result); + +/* + disposition := "Content-Disposition" ":" + disposition-type + *(";" disposition-parm) + +*/ + + +int mailmime_disposition_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition ** result) +{ + size_t final_token; + size_t cur_token; + struct mailmime_disposition_type * dsp_type; + clist * list; + struct mailmime_disposition * dsp; + int r; + int res; + + cur_token = * index; + + r = mailmime_disposition_type_parse(message, length, &cur_token, + &dsp_type); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_type; + } + + while (1) { + struct mailmime_disposition_parm * param; + + final_token = cur_token; + r = mailimf_unstrict_char_parse(message, length, &cur_token, ';'); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto free_list; + } + + param = NULL; + r = mailmime_disposition_parm_parse(message, length, &cur_token, ¶m); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + cur_token = final_token; + break; + } + else { + res = r; + goto free_list; + } + + r = clist_append(list, param); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + } + + dsp = mailmime_disposition_new(dsp_type, list); + if (dsp == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = dsp; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_disposition_parm_free, NULL); + clist_free(list); + free_type: + mailmime_disposition_type_free(dsp_type); + err: + return res; +} + +/* + disposition-type := "inline" + / "attachment" + / extension-token + ; values are not case-sensitive + +*/ + + + +int +mailmime_disposition_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_type ** result) +{ + size_t cur_token; + int type; + char * extension; + struct mailmime_disposition_type * dsp_type; + int r; + int res; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + type = MAILMIME_DISPOSITION_TYPE_ERROR; /* XXX - removes a gcc warning */ + + extension = NULL; + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "inline"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISPOSITION_TYPE_INLINE; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "attachment"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISPOSITION_TYPE_ATTACHMENT; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_extension_token_parse(message, length, &cur_token, + &extension); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISPOSITION_TYPE_EXTENSION; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + dsp_type = mailmime_disposition_type_new(type, extension); + if (dsp_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = dsp_type; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (extension != NULL) + free(extension); + err: + return res; +} + +/* + disposition-parm := filename-parm + / creation-date-parm + / modification-date-parm + / read-date-parm + / size-parm + / parameter +*/ + + +int mailmime_disposition_guess_type(const char * message, size_t length, + size_t index) +{ + if (index >= length) + return MAILMIME_DISPOSITION_PARM_PARAMETER; + + switch ((char) toupper((unsigned char) message[index])) { + case 'F': + return MAILMIME_DISPOSITION_PARM_FILENAME; + case 'C': + return MAILMIME_DISPOSITION_PARM_CREATION_DATE; + case 'M': + return MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE; + case 'R': + return MAILMIME_DISPOSITION_PARM_READ_DATE; + case 'S': + return MAILMIME_DISPOSITION_PARM_SIZE; + default: + return MAILMIME_DISPOSITION_PARM_PARAMETER; + } +} + +static int +mailmime_disposition_parm_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_parm ** + result) +{ + char * filename; + char * creation_date; + char * modification_date; + char * read_date; + size_t size; + struct mailmime_parameter * parameter; + size_t cur_token; + struct mailmime_disposition_parm * dsp_parm; + int type; + int guessed_type; + int r; + int res; + + cur_token = * index; + + filename = NULL; + creation_date = NULL; + modification_date = NULL; + read_date = NULL; + size = 0; + parameter = NULL; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + guessed_type = mailmime_disposition_guess_type(message, length, cur_token); + + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + + switch (guessed_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + r = mailmime_filename_parm_parse(message, length, &cur_token, + &filename); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + r = mailmime_creation_date_parm_parse(message, length, &cur_token, + &creation_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + r = mailmime_modification_date_parm_parse(message, length, &cur_token, + &modification_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + r = mailmime_read_date_parm_parse(message, length, &cur_token, + &read_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + r = mailmime_size_parm_parse(message, length, &cur_token, + &size); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + } + + if (type == MAILMIME_DISPOSITION_PARM_PARAMETER) { + r = mailmime_parameter_parse(message, length, &cur_token, + ¶meter); + if (r != MAILIMF_NO_ERROR) { + type = guessed_type; + res = r; + goto err; + } + } + + dsp_parm = mailmime_disposition_parm_new(type, filename, creation_date, + modification_date, read_date, + size, parameter); + + if (dsp_parm == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = dsp_parm; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (filename != NULL) + mailmime_filename_parm_free(dsp_parm->pa_data.pa_filename); + if (creation_date != NULL) + mailmime_creation_date_parm_free(dsp_parm->pa_data.pa_creation_date); + if (modification_date != NULL) + mailmime_modification_date_parm_free(dsp_parm->pa_data.pa_modification_date); + if (read_date != NULL) + mailmime_read_date_parm_free(dsp_parm->pa_data.pa_read_date); + if (parameter != NULL) + mailmime_parameter_free(dsp_parm->pa_data.pa_parameter); + err: + return res; +} + +/* + filename-parm := "filename" "=" value +*/ + +static int +mailmime_filename_parm_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * value; + int r; + size_t cur_token; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "filename"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_value_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + creation-date-parm := "creation-date" "=" quoted-date-time +*/ + +static int +mailmime_creation_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * value; + int r; + size_t cur_token; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "creation-date"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + modification-date-parm := "modification-date" "=" quoted-date-time +*/ + +static int +mailmime_modification_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * value; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "modification-date"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + read-date-parm := "read-date" "=" quoted-date-time +*/ + +static int +mailmime_read_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * value; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "read-date"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + size-parm := "size" "=" 1*DIGIT +*/ + +static int +mailmime_size_parm_parse(const char * message, size_t length, + size_t * index, size_t * result) +{ + uint32_t value; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "size"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + quoted-date-time := quoted-string + ; contents MUST be an RFC 822 `date-time' + ; numeric timezones (+HHMM or -HHMM) MUST be used +*/ + +static int +mailmime_quoted_date_time_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_quoted_string_parse(message, length, index, result); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_disposition.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_disposition.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,62 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_disposition.h,v 1.10 2004/11/21 21:53:39 hoa Exp $ + */ + +#ifndef MAILMIME_DISPOSITION_H + +#define MAILMIME_DISPOSITION_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailmime_types.h> + +int mailmime_disposition_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition ** result); + +int +mailmime_disposition_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_type ** result); + +int mailmime_disposition_guess_type(const char * message, size_t length, + size_t index); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_types.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_types.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,757 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_types.c,v 1.20 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmime_types.h" +#include "mmapstring.h" + +#include <string.h> +#include <stdlib.h> + +void mailmime_attribute_free(char * attribute) +{ + mailmime_token_free(attribute); +} + + + +struct mailmime_composite_type * +mailmime_composite_type_new(int ct_type, char * ct_token) +{ + struct mailmime_composite_type * ct; + + ct = malloc(sizeof(* ct)); + if (ct == NULL) + return NULL; + + ct->ct_type = ct_type; + ct->ct_token = ct_token; + + return ct; +} + +void mailmime_composite_type_free(struct mailmime_composite_type * ct) +{ + if (ct->ct_token != NULL) + mailmime_extension_token_free(ct->ct_token); + free(ct); +} + + +struct mailmime_content * +mailmime_content_new(struct mailmime_type * ct_type, + char * ct_subtype, + clist * ct_parameters) +{ + struct mailmime_content * content; + + content = malloc(sizeof(* content)); + if (content == NULL) + return NULL; + + content->ct_type = ct_type; + content->ct_subtype = ct_subtype; + content->ct_parameters = ct_parameters; + + return content; +} + +void mailmime_content_free(struct mailmime_content * content) +{ + mailmime_type_free(content->ct_type); + mailmime_subtype_free(content->ct_subtype); + if (content->ct_parameters != NULL) { + clist_foreach(content->ct_parameters, + (clist_func) mailmime_parameter_free, NULL); + clist_free(content->ct_parameters); + } + + free(content); +} + + +void mailmime_description_free(char * description) +{ + free(description); +} + +struct mailmime_discrete_type * +mailmime_discrete_type_new(int dt_type, char * dt_extension) +{ + struct mailmime_discrete_type * discrete_type; + + discrete_type = malloc(sizeof(* discrete_type)); + if (discrete_type == NULL) + return NULL; + + discrete_type->dt_type = dt_type; + discrete_type->dt_extension = dt_extension; + + return discrete_type; +} + +void mailmime_discrete_type_free(struct mailmime_discrete_type * discrete_type) +{ + if (discrete_type->dt_extension != NULL) + mailmime_extension_token_free(discrete_type->dt_extension); + free(discrete_type); +} + +void mailmime_encoding_free(struct mailmime_mechanism * encoding) +{ + mailmime_mechanism_free(encoding); +} + +void mailmime_extension_token_free(char * extension) +{ + mailmime_token_free(extension); +} + +void mailmime_id_free(char * id) +{ + mailimf_msg_id_free(id); +} + +struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token) +{ + struct mailmime_mechanism * mechanism; + + mechanism = malloc(sizeof(* mechanism)); + if (mechanism == NULL) + return NULL; + + mechanism->enc_type = enc_type; + mechanism->enc_token = enc_token; + + return mechanism; +} + +void mailmime_mechanism_free(struct mailmime_mechanism * mechanism) +{ + if (mechanism->enc_token != NULL) + mailmime_token_free(mechanism->enc_token); + free(mechanism); +} + +struct mailmime_parameter * +mailmime_parameter_new(char * pa_name, char * pa_value) +{ + struct mailmime_parameter * parameter; + + parameter = malloc(sizeof(* parameter)); + if (parameter == NULL) + return NULL; + + parameter->pa_name = pa_name; + parameter->pa_value = pa_value; + + return parameter; +} + +void mailmime_parameter_free(struct mailmime_parameter * parameter) +{ + mailmime_attribute_free(parameter->pa_name); + mailmime_value_free(parameter->pa_value); + free(parameter); +} + + +void mailmime_subtype_free(char * subtype) +{ + mailmime_extension_token_free(subtype); +} + + +void mailmime_token_free(char * token) +{ + free(token); +} + + +struct mailmime_type * +mailmime_type_new(int tp_type, + struct mailmime_discrete_type * tp_discrete_type, + struct mailmime_composite_type * tp_composite_type) +{ + struct mailmime_type * mime_type; + + mime_type = malloc(sizeof(* mime_type)); + if (mime_type == NULL) + return NULL; + + mime_type->tp_type = tp_type; + switch (tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mime_type->tp_data.tp_discrete_type = tp_discrete_type; + break; + case MAILMIME_TYPE_COMPOSITE_TYPE: + mime_type->tp_data.tp_composite_type = tp_composite_type; + break; + } + + return mime_type; +} + +void mailmime_type_free(struct mailmime_type * type) +{ + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mailmime_discrete_type_free(type->tp_data.tp_discrete_type); + break; + case MAILMIME_TYPE_COMPOSITE_TYPE: + mailmime_composite_type_free(type->tp_data.tp_composite_type); + break; + } + free(type); +} + +void mailmime_value_free(char * value) +{ + free(value); +} + + +/* +void mailmime_x_token_free(gchar * x_token) +{ + g_free(x_token); +} +*/ + +struct mailmime_field * +mailmime_field_new(int fld_type, + struct mailmime_content * fld_content, + struct mailmime_mechanism * fld_encoding, + char * fld_id, + char * fld_description, + uint32_t fld_version, + struct mailmime_disposition * fld_disposition, + struct mailmime_language * fld_language) +{ + struct mailmime_field * field; + + field = malloc(sizeof(* field)); + if (field == NULL) + return NULL; + field->fld_type = fld_type; + + switch (fld_type) { + case MAILMIME_FIELD_TYPE: + field->fld_data.fld_content = fld_content; + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + field->fld_data.fld_encoding = fld_encoding; + break; + case MAILMIME_FIELD_ID: + field->fld_data.fld_id = fld_id; + break; + case MAILMIME_FIELD_DESCRIPTION: + field->fld_data.fld_description = fld_description; + break; + case MAILMIME_FIELD_VERSION: + field->fld_data.fld_version = fld_version; + break; + case MAILMIME_FIELD_DISPOSITION: + field->fld_data.fld_disposition = fld_disposition; + break; + case MAILMIME_FIELD_LANGUAGE: + field->fld_data.fld_language = fld_language; + break; + } + return field; +} + +void mailmime_field_free(struct mailmime_field * field) +{ + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + if (field->fld_data.fld_content != NULL) + mailmime_content_free(field->fld_data.fld_content); + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + if (field->fld_data.fld_encoding != NULL) + mailmime_encoding_free(field->fld_data.fld_encoding); + break; + case MAILMIME_FIELD_ID: + if (field->fld_data.fld_id != NULL) + mailmime_id_free(field->fld_data.fld_id); + break; + case MAILMIME_FIELD_DESCRIPTION: + if (field->fld_data.fld_description != NULL) + mailmime_description_free(field->fld_data.fld_description); + break; + case MAILMIME_FIELD_DISPOSITION: + if (field->fld_data.fld_disposition != NULL) + mailmime_disposition_free(field->fld_data.fld_disposition); + break; + case MAILMIME_FIELD_LANGUAGE: + if (field->fld_data.fld_language != NULL) + mailmime_language_free(field->fld_data.fld_language); + break; + } + + free(field); +} + +struct mailmime_fields * mailmime_fields_new(clist * fld_list) +{ + struct mailmime_fields * fields; + + fields = malloc(sizeof(* fields)); + if (fields == NULL) + return NULL; + + fields->fld_list = fld_list; + + return fields; +} + +void mailmime_fields_free(struct mailmime_fields * fields) +{ + clist_foreach(fields->fld_list, (clist_func) mailmime_field_free, NULL); + clist_free(fields->fld_list); + free(fields); +} + + +/* +struct mailmime_body_part * +mailmime_body_part_new(gchar * text, guint32 size) +{ + struct mailmime_body_part * body_part; + + body_part = g_new(struct mailmime_body_part, 1); + if (body_part == NULL) + return NULL; + + body_part->text = text; + body_part->size = size; + + return body_part; +} + +void mailmime_body_part_free(struct mailmime_body_part * body_part) +{ + g_free(body_part); +} +*/ + +struct mailmime_multipart_body * +mailmime_multipart_body_new(clist * bd_list) +{ + struct mailmime_multipart_body * mp_body; + + mp_body = malloc(sizeof(* mp_body)); + if (mp_body == NULL) + return NULL; + + mp_body->bd_list = bd_list; + + return mp_body; +} + +void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body) +{ + clist_foreach(mp_body->bd_list, (clist_func) mailimf_body_free, NULL); + clist_free(mp_body->bd_list); + free(mp_body); +} + + + + +struct mailmime * mailmime_new(int mm_type, + const char * mm_mime_start, size_t mm_length, + struct mailmime_fields * mm_mime_fields, + struct mailmime_content * mm_content_type, + struct mailmime_data * mm_body, + struct mailmime_data * mm_preamble, + struct mailmime_data * mm_epilogue, + clist * mm_mp_list, + struct mailimf_fields * mm_fields, + struct mailmime * mm_msg_mime) +{ + struct mailmime * mime; + clistiter * cur; + + mime = malloc(sizeof(* mime)); + if (mime == NULL) + return NULL; + + mime->mm_parent = NULL; + mime->mm_parent_type = MAILMIME_NONE; + mime->mm_multipart_pos = NULL; + + mime->mm_type = mm_type; + mime->mm_mime_start = mm_mime_start; + mime->mm_length = mm_length; + mime->mm_mime_fields = mm_mime_fields; + mime->mm_content_type = mm_content_type; + + mime->mm_body = mm_body; + + switch (mm_type) { + case MAILMIME_SINGLE: + mime->mm_data.mm_single = mm_body; + break; + + case MAILMIME_MULTIPLE: + mime->mm_data.mm_multipart.mm_preamble = mm_preamble; + mime->mm_data.mm_multipart.mm_epilogue = mm_epilogue; + mime->mm_data.mm_multipart.mm_mp_list = mm_mp_list; + + for(cur = clist_begin(mm_mp_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime * submime; + + submime = clist_content(cur); + submime->mm_parent = mime; + submime->mm_parent_type = MAILMIME_MULTIPLE; + submime->mm_multipart_pos = cur; + } + break; + + case MAILMIME_MESSAGE: + mime->mm_data.mm_message.mm_fields = mm_fields; + mime->mm_data.mm_message.mm_msg_mime = mm_msg_mime; + if (mm_msg_mime != NULL) { + mm_msg_mime->mm_parent = mime; + mm_msg_mime->mm_parent_type = MAILMIME_MESSAGE; + } + break; + + } + + return mime; +} + +void mailmime_free(struct mailmime * mime) +{ + switch (mime->mm_type) { + case MAILMIME_SINGLE: + if ((mime->mm_body == NULL) && (mime->mm_data.mm_single != NULL)) + mailmime_data_free(mime->mm_data.mm_single); + /* do nothing */ + break; + + case MAILMIME_MULTIPLE: + if (mime->mm_data.mm_multipart.mm_preamble != NULL) + mailmime_data_free(mime->mm_data.mm_multipart.mm_preamble); + if (mime->mm_data.mm_multipart.mm_epilogue != NULL) + mailmime_data_free(mime->mm_data.mm_multipart.mm_epilogue); + clist_foreach(mime->mm_data.mm_multipart.mm_mp_list, + (clist_func) mailmime_free, NULL); + clist_free(mime->mm_data.mm_multipart.mm_mp_list); + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_fields != NULL) + mailimf_fields_free(mime->mm_data.mm_message.mm_fields); + if (mime->mm_data.mm_message.mm_msg_mime != NULL) + mailmime_free(mime->mm_data.mm_message.mm_msg_mime); + break; + + } + if (mime->mm_body != NULL) + mailmime_data_free(mime->mm_body); + + if (mime->mm_mime_fields != NULL) + mailmime_fields_free(mime->mm_mime_fields); + if (mime->mm_content_type != NULL) + mailmime_content_free(mime->mm_content_type); + free(mime); +} + + + +struct mailmime_encoded_word * +mailmime_encoded_word_new(char * wd_charset, char * wd_text) +{ + struct mailmime_encoded_word * ew; + + ew = malloc(sizeof(* ew)); + if (ew == NULL) + return NULL; + ew->wd_charset = wd_charset; + ew->wd_text = wd_text; + + return ew; +} + +void mailmime_charset_free(char * charset) +{ + free(charset); +} + +void mailmime_encoded_text_free(char * text) +{ + free(text); +} + +void mailmime_encoded_word_free(struct mailmime_encoded_word * ew) +{ + mailmime_charset_free(ew->wd_charset); + mailmime_encoded_text_free(ew->wd_text); + free(ew); +} + + + +/* mailmime_disposition */ + + +struct mailmime_disposition * +mailmime_disposition_new(struct mailmime_disposition_type * dsp_type, + clist * dsp_parms) +{ + struct mailmime_disposition * dsp; + + dsp = malloc(sizeof(* dsp)); + if (dsp == NULL) + return NULL; + dsp->dsp_type = dsp_type; + dsp->dsp_parms = dsp_parms; + + return dsp; +} + +void mailmime_disposition_free(struct mailmime_disposition * dsp) +{ + mailmime_disposition_type_free(dsp->dsp_type); + clist_foreach(dsp->dsp_parms, + (clist_func) mailmime_disposition_parm_free, NULL); + clist_free(dsp->dsp_parms); + free(dsp); +} + + + +struct mailmime_disposition_type * +mailmime_disposition_type_new(int dsp_type, char * dsp_extension) +{ + struct mailmime_disposition_type * m_dsp_type; + + m_dsp_type = malloc(sizeof(* m_dsp_type)); + if (m_dsp_type == NULL) + return NULL; + + m_dsp_type->dsp_type = dsp_type; + m_dsp_type->dsp_extension = dsp_extension; + + return m_dsp_type; +} + +void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type) +{ + if (dsp_type->dsp_extension != NULL) + free(dsp_type->dsp_extension); + free(dsp_type); +} + + +struct mailmime_disposition_parm * +mailmime_disposition_parm_new(int pa_type, + char * pa_filename, + char * pa_creation_date, + char * pa_modification_date, + char * pa_read_date, + size_t pa_size, + struct mailmime_parameter * pa_parameter) +{ + struct mailmime_disposition_parm * dsp_parm; + + dsp_parm = malloc(sizeof(* dsp_parm)); + if (dsp_parm == NULL) + return NULL; + + dsp_parm->pa_type = pa_type; + switch (pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + dsp_parm->pa_data.pa_filename = pa_filename; + break; + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + dsp_parm->pa_data.pa_creation_date = pa_creation_date; + break; + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + dsp_parm->pa_data.pa_modification_date = pa_modification_date; + break; + case MAILMIME_DISPOSITION_PARM_READ_DATE: + dsp_parm->pa_data.pa_read_date = pa_read_date; + break; + case MAILMIME_DISPOSITION_PARM_SIZE: + dsp_parm->pa_data.pa_size = pa_size; + break; + case MAILMIME_DISPOSITION_PARM_PARAMETER: + dsp_parm->pa_data.pa_parameter = pa_parameter; + break; + } + + return dsp_parm; +} + +void mailmime_disposition_parm_free(struct mailmime_disposition_parm * + dsp_parm) +{ + switch (dsp_parm->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + mailmime_filename_parm_free(dsp_parm->pa_data.pa_filename); + break; + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + mailmime_creation_date_parm_free(dsp_parm->pa_data.pa_creation_date); + break; + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + mailmime_modification_date_parm_free(dsp_parm->pa_data.pa_modification_date); + break; + case MAILMIME_DISPOSITION_PARM_READ_DATE: + mailmime_read_date_parm_free(dsp_parm->pa_data.pa_read_date); + break; + case MAILMIME_DISPOSITION_PARM_PARAMETER: + mailmime_parameter_free(dsp_parm->pa_data.pa_parameter); + break; + } + + free(dsp_parm); +} + + +void mailmime_filename_parm_free(char * filename) +{ + mailmime_value_free(filename); +} + +void mailmime_creation_date_parm_free(char * date) +{ + mailmime_quoted_date_time_free(date); +} + +void mailmime_modification_date_parm_free(char * date) +{ + mailmime_quoted_date_time_free(date); +} + +void mailmime_read_date_parm_free(char * date) +{ + mailmime_quoted_date_time_free(date); +} + +void mailmime_quoted_date_time_free(char * date) +{ + mailimf_quoted_string_free(date); +} + +struct mailmime_section * mailmime_section_new(clist * sec_list) +{ + struct mailmime_section * section; + + section = malloc(sizeof(* section)); + if (section == NULL) + return NULL; + + section->sec_list = sec_list; + + return section; +} + +void mailmime_section_free(struct mailmime_section * section) +{ + clist_foreach(section->sec_list, (clist_func) free, NULL); + clist_free(section->sec_list); + free(section); +} + + + +struct mailmime_language * mailmime_language_new(clist * lg_list) +{ + struct mailmime_language * lang; + + lang = malloc(sizeof(* lang)); + if (lang == NULL) + return NULL; + + lang->lg_list = lg_list; + + return lang; +} + +void mailmime_language_free(struct mailmime_language * lang) +{ + clist_foreach(lang->lg_list, (clist_func) mailimf_atom_free, NULL); + clist_free(lang->lg_list); + free(lang); +} + +void mailmime_decoded_part_free(char * part) +{ + mmap_string_unref(part); +} + +struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, + int dt_encoded, const char * dt_data, size_t dt_length, char * dt_filename) +{ + struct mailmime_data * mime_data; + + mime_data = malloc(sizeof(* mime_data)); + if (mime_data == NULL) + return NULL; + + mime_data->dt_type = dt_type; + mime_data->dt_encoding = dt_encoding; + mime_data->dt_encoded = dt_encoded; + switch (dt_type) { + case MAILMIME_DATA_TEXT: + mime_data->dt_data.dt_text.dt_data = dt_data; + mime_data->dt_data.dt_text.dt_length = dt_length; + break; + case MAILMIME_DATA_FILE: + mime_data->dt_data.dt_filename = dt_filename; + break; + } + + return mime_data; +} + +void mailmime_data_free(struct mailmime_data * mime_data) +{ + switch (mime_data->dt_type) { + case MAILMIME_DATA_FILE: + free(mime_data->dt_data.dt_filename); + break; + } + free(mime_data); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,496 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_types.h,v 1.32 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILMIME_TYPES_H + +#define MAILMIME_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LIBETPAN_CONFIG_H +# include <libetpan/libetpan-config.h> +#endif + +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#include <libetpan/mailimf.h> +#include <libetpan/clist.h> + +enum { + MAILMIME_COMPOSITE_TYPE_ERROR, + MAILMIME_COMPOSITE_TYPE_MESSAGE, + MAILMIME_COMPOSITE_TYPE_MULTIPART, + MAILMIME_COMPOSITE_TYPE_EXTENSION +}; + +struct mailmime_composite_type { + int ct_type; + char * ct_token; +}; + + +struct mailmime_content { + struct mailmime_type * ct_type; + char * ct_subtype; + clist * ct_parameters; /* elements are (struct mailmime_parameter *) */ +}; + + +enum { + MAILMIME_DISCRETE_TYPE_ERROR, + MAILMIME_DISCRETE_TYPE_TEXT, + MAILMIME_DISCRETE_TYPE_IMAGE, + MAILMIME_DISCRETE_TYPE_AUDIO, + MAILMIME_DISCRETE_TYPE_VIDEO, + MAILMIME_DISCRETE_TYPE_APPLICATION, + MAILMIME_DISCRETE_TYPE_EXTENSION +}; + +struct mailmime_discrete_type { + int dt_type; + char * dt_extension; +}; + +enum { + MAILMIME_FIELD_NONE, + MAILMIME_FIELD_TYPE, + MAILMIME_FIELD_TRANSFER_ENCODING, + MAILMIME_FIELD_ID, + MAILMIME_FIELD_DESCRIPTION, + MAILMIME_FIELD_VERSION, + MAILMIME_FIELD_DISPOSITION, + MAILMIME_FIELD_LANGUAGE +}; + +struct mailmime_field { + int fld_type; + union { + struct mailmime_content * fld_content; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + struct mailmime_language * fld_language; + } fld_data; +}; + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_mechanism { + int enc_type; + char * enc_token; +}; + + +struct mailmime_fields { + clist * fld_list; /* list of (struct mailmime_field *) */ +}; + + +struct mailmime_parameter { + char * pa_name; + char * pa_value; +}; + +enum { + MAILMIME_TYPE_ERROR, + MAILMIME_TYPE_DISCRETE_TYPE, + MAILMIME_TYPE_COMPOSITE_TYPE +}; + +struct mailmime_type { + int tp_type; + union { + struct mailmime_discrete_type * tp_discrete_type; + struct mailmime_composite_type * tp_composite_type; + } tp_data; +}; + +LIBETPAN_EXPORT +void mailmime_attribute_free(char * attribute); + +LIBETPAN_EXPORT +struct mailmime_composite_type * +mailmime_composite_type_new(int ct_type, char * ct_token); + +LIBETPAN_EXPORT +void mailmime_composite_type_free(struct mailmime_composite_type * ct); + +LIBETPAN_EXPORT +struct mailmime_content * +mailmime_content_new(struct mailmime_type * ct_type, + char * ct_subtype, + clist * ct_parameters); + +LIBETPAN_EXPORT +void mailmime_content_free(struct mailmime_content * content); + +LIBETPAN_EXPORT +void mailmime_description_free(char * description); + +LIBETPAN_EXPORT +struct mailmime_discrete_type * +mailmime_discrete_type_new(int dt_type, char * dt_extension); + +LIBETPAN_EXPORT +void mailmime_discrete_type_free(struct mailmime_discrete_type * + discrete_type); + +LIBETPAN_EXPORT +void mailmime_encoding_free(struct mailmime_mechanism * encoding); + +LIBETPAN_EXPORT +void mailmime_extension_token_free(char * extension); + +LIBETPAN_EXPORT +void mailmime_id_free(char * id); + +LIBETPAN_EXPORT +struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token); + +LIBETPAN_EXPORT +void mailmime_mechanism_free(struct mailmime_mechanism * mechanism); + +LIBETPAN_EXPORT +struct mailmime_parameter * +mailmime_parameter_new(char * pa_name, char * pa_value); + +LIBETPAN_EXPORT +void mailmime_parameter_free(struct mailmime_parameter * parameter); + +LIBETPAN_EXPORT +void mailmime_subtype_free(char * subtype); + +LIBETPAN_EXPORT +void mailmime_token_free(char * token); + +LIBETPAN_EXPORT +struct mailmime_type * +mailmime_type_new(int tp_type, + struct mailmime_discrete_type * tp_discrete_type, + struct mailmime_composite_type * tp_composite_type); + +LIBETPAN_EXPORT +void mailmime_type_free(struct mailmime_type * type); + +LIBETPAN_EXPORT +void mailmime_value_free(char * value); + + + +struct mailmime_language { + clist * lg_list; /* atom (char *) */ +}; + +LIBETPAN_EXPORT +struct mailmime_language * mailmime_language_new(clist * lg_list); + +LIBETPAN_EXPORT +void mailmime_language_free(struct mailmime_language * lang); + + +/* +void mailmime_x_token_free(gchar * x_token); +*/ + +LIBETPAN_EXPORT +struct mailmime_field * +mailmime_field_new(int fld_type, + struct mailmime_content * fld_content, + struct mailmime_mechanism * fld_encoding, + char * fld_id, + char * fld_description, + uint32_t fld_version, + struct mailmime_disposition * fld_disposition, + struct mailmime_language * fld_language); + +LIBETPAN_EXPORT +void mailmime_field_free(struct mailmime_field * field); + +LIBETPAN_EXPORT +struct mailmime_fields * mailmime_fields_new(clist * fld_list); + +LIBETPAN_EXPORT +void mailmime_fields_free(struct mailmime_fields * fields); + + +struct mailmime_multipart_body { + clist * bd_list; +}; + +LIBETPAN_EXPORT +struct mailmime_multipart_body * +mailmime_multipart_body_new(clist * bd_list); + +LIBETPAN_EXPORT +void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body); + + +enum { + MAILMIME_DATA_TEXT, + MAILMIME_DATA_FILE +}; + +struct mailmime_data { + int dt_type; + int dt_encoding; + int dt_encoded; + union { + struct { + const char * dt_data; + size_t dt_length; + } dt_text; + char * dt_filename; + } dt_data; +}; + +LIBETPAN_EXPORT +struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, + int dt_encoded, const char * dt_data, size_t dt_length, + char * dt_filename); + +LIBETPAN_EXPORT +void mailmime_data_free(struct mailmime_data * mime_data); + + +enum { + MAILMIME_NONE, + MAILMIME_SINGLE, + MAILMIME_MULTIPLE, + MAILMIME_MESSAGE +}; + +struct mailmime { + /* parent information */ + int mm_parent_type; + struct mailmime * mm_parent; + clistiter * mm_multipart_pos; + + int mm_type; + const char * mm_mime_start; + size_t mm_length; + + struct mailmime_fields * mm_mime_fields; + struct mailmime_content * mm_content_type; + + struct mailmime_data * mm_body; + union { + /* single part */ + struct mailmime_data * mm_single; /* XXX - was body */ + + /* multi-part */ + struct { + struct mailmime_data * mm_preamble; + struct mailmime_data * mm_epilogue; + clist * mm_mp_list; + } mm_multipart; + + /* message */ + struct { + struct mailimf_fields * mm_fields; + struct mailmime * mm_msg_mime; + } mm_message; + + } mm_data; +}; + +LIBETPAN_EXPORT +struct mailmime * mailmime_new(int mm_type, + const char * mm_mime_start, size_t mm_length, + struct mailmime_fields * mm_mime_fields, + struct mailmime_content * mm_content_type, + struct mailmime_data * mm_body, + struct mailmime_data * mm_preamble, + struct mailmime_data * mm_epilogue, + clist * mm_mp_list, + struct mailimf_fields * mm_fields, + struct mailmime * mm_msg_mime); + +LIBETPAN_EXPORT +void mailmime_free(struct mailmime * mime); + +struct mailmime_encoded_word { + char * wd_charset; + char * wd_text; +}; + +LIBETPAN_EXPORT +struct mailmime_encoded_word * +mailmime_encoded_word_new(char * wd_charset, char * wd_text); + +LIBETPAN_EXPORT +void mailmime_encoded_word_free(struct mailmime_encoded_word * ew); + +LIBETPAN_EXPORT +void mailmime_charset_free(char * charset); + +LIBETPAN_EXPORT +void mailmime_encoded_text_free(char * text); + + +struct mailmime_disposition { + struct mailmime_disposition_type * dsp_type; + clist * dsp_parms; /* struct mailmime_disposition_parm */ +}; + + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition_type { + int dsp_type; + char * dsp_extension; +}; + + +enum { + MAILMIME_DISPOSITION_PARM_FILENAME, + MAILMIME_DISPOSITION_PARM_CREATION_DATE, + MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, + MAILMIME_DISPOSITION_PARM_READ_DATE, + MAILMIME_DISPOSITION_PARM_SIZE, + MAILMIME_DISPOSITION_PARM_PARAMETER +}; + +struct mailmime_disposition_parm { + int pa_type; + union { + char * pa_filename; + char * pa_creation_date; + char * pa_modification_date; + char * pa_read_date; + size_t pa_size; + struct mailmime_parameter * pa_parameter; + } pa_data; +}; + +LIBETPAN_EXPORT +struct mailmime_disposition * +mailmime_disposition_new(struct mailmime_disposition_type * dsp_type, + clist * dsp_parms); + +LIBETPAN_EXPORT +void mailmime_disposition_free(struct mailmime_disposition * dsp); + +LIBETPAN_EXPORT +struct mailmime_disposition_type * +mailmime_disposition_type_new(int dt_type, char * dt_extension); + +LIBETPAN_EXPORT +void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type); + +LIBETPAN_EXPORT +struct mailmime_disposition_parm * +mailmime_disposition_parm_new(int pa_type, + char * pa_filename, + char * pa_creation_date, + char * pa_modification_date, + char * pa_read_date, + size_t pa_size, + struct mailmime_parameter * pa_parameter); + +LIBETPAN_EXPORT +void mailmime_disposition_parm_free(struct mailmime_disposition_parm * + dsp_parm); + +LIBETPAN_EXPORT +void mailmime_filename_parm_free(char * filename); + +LIBETPAN_EXPORT +void mailmime_creation_date_parm_free(char * date); + +LIBETPAN_EXPORT +void mailmime_modification_date_parm_free(char * date); + +LIBETPAN_EXPORT +void mailmime_read_date_parm_free(char * date); + +LIBETPAN_EXPORT +void mailmime_quoted_date_time_free(char * date); + +struct mailmime_section { + clist * sec_list; /* list of (uint32 *) */ +}; + +LIBETPAN_EXPORT +struct mailmime_section * mailmime_section_new(clist * list); + +LIBETPAN_EXPORT +void mailmime_section_free(struct mailmime_section * section); + + +LIBETPAN_EXPORT +void mailmime_decoded_part_free(char * part); + +struct mailmime_single_fields { + struct mailmime_content * fld_content; + char * fld_content_charset; + char * fld_content_boundary; + char * fld_content_name; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + char * fld_disposition_filename; + char * fld_disposition_creation_date; + char * fld_disposition_modification_date; + char * fld_disposition_read_date; + size_t fld_disposition_size; + struct mailmime_language * fld_language; +}; + +#ifdef __cplusplus +} +#endif + +#endif + Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_types_helper.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_types_helper.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1394 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_types_helper.c,v 1.26 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmime_types_helper.h" + +#include "clist.h" +#include "mailmime.h" + +#include <string.h> +#include <time.h> +#include <sys/types.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <stdlib.h> +#ifdef _MSC_VER +# include "win_etpan.h" +#endif + +#define MIME_VERSION (1 << 16) + +int mailmime_transfer_encoding_get(struct mailmime_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) + return field->fld_data.fld_encoding->enc_type; + } + + return MAILMIME_MECHANISM_8BIT; +} + +struct mailmime_disposition * +mailmime_disposition_new_filename(int type, char * filename) +{ + return mailmime_disposition_new_with_data(type, filename, + NULL, NULL, NULL, (size_t) -1); + +} + +struct mailmime_fields * mailmime_fields_new_empty(void) +{ + clist * list; + struct mailmime_fields * fields; + + list = clist_new(); + if (list == NULL) + goto err; + + fields = mailmime_fields_new(list); + if (fields == NULL) + goto free; + + return fields; + + free: + clist_free(list); + err: + return NULL; +} + +int mailmime_fields_add(struct mailmime_fields * fields, + struct mailmime_field * field) +{ + int r; + + r = clist_append(fields->fld_list, field); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +static void mailmime_field_detach(struct mailmime_field * field) +{ + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + field->fld_data.fld_content = NULL; + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + field->fld_data.fld_encoding = NULL; + break; + case MAILMIME_FIELD_ID: + field->fld_data.fld_id = NULL; + break; + case MAILMIME_FIELD_DESCRIPTION: + field->fld_data.fld_description = NULL; + break; + case MAILMIME_FIELD_DISPOSITION: + field->fld_data.fld_disposition = NULL; + break; + case MAILMIME_FIELD_LANGUAGE: + field->fld_data.fld_language = NULL; + break; + } +} + +struct mailmime_fields * +mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language) +{ + struct mailmime_field * field; + struct mailmime_fields * fields; + int r; + + fields = mailmime_fields_new_empty(); + if (fields == NULL) + goto err; + +#if 0 + if (content != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_TYPE, + content, NULL, NULL, NULL, 0, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } +#endif + + if (encoding != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, encoding, NULL, NULL, 0, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (id != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_ID, + NULL, NULL, id, NULL, 0, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (description != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_DESCRIPTION, + NULL, NULL, NULL, description, 0, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (disposition != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION, + NULL, NULL, NULL, NULL, 0, disposition, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (language != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION, + NULL, NULL, NULL, NULL, 0, NULL, language); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + return fields; + + free: + clist_foreach(fields->fld_list, (clist_func) mailmime_field_detach, NULL); + mailmime_fields_free(fields); + err: + return NULL; +} + +struct mailmime_fields * +mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language) +{ + struct mailmime_field * field; + struct mailmime_fields * fields; + int r; + + fields = mailmime_fields_new_with_data(encoding, id, description, + disposition, language); + if (fields == NULL) + goto err; + + field = mailmime_field_new(MAILMIME_FIELD_VERSION, + NULL, NULL, NULL, NULL, MIME_VERSION, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + + return fields; + + free: + clist_foreach(fields->fld_list, (clist_func) mailmime_field_detach, NULL); + mailmime_fields_free(fields); + err: + return NULL; +} + + +struct mailmime_content * mailmime_get_content_message(void) +{ + clist * list; + struct mailmime_composite_type * composite_type; + struct mailmime_type * mime_type; + struct mailmime_content * content; + char * subtype; + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, + NULL); + if (composite_type == NULL) + goto err; + + mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, + NULL, composite_type); + if (mime_type == NULL) + goto free_composite; + composite_type = NULL; + + list = clist_new(); + if (list == NULL) + goto free_mime_type; + + subtype = strdup("rfc822"); + if (subtype == NULL) + goto free_list; + + content = mailmime_content_new(mime_type, subtype, list); + if (content == NULL) + goto free_subtype; + + return content; + + free_subtype: + free(subtype); + free_list: + clist_free(list); + free_mime_type: + mailmime_type_free(mime_type); + free_composite: + if (composite_type != NULL) + mailmime_composite_type_free(composite_type); + err: + return NULL; +} + +struct mailmime_content * mailmime_get_content_text(void) +{ + clist * list; + struct mailmime_discrete_type * discrete_type; + struct mailmime_type * mime_type; + struct mailmime_content * content; + char * subtype; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, + NULL); + if (discrete_type == NULL) + goto err; + + mime_type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, + discrete_type, NULL); + if (mime_type == NULL) + goto free_discrete; + discrete_type = NULL; + + list = clist_new(); + if (list == NULL) + goto free_type; + + subtype = strdup("plain"); + if (subtype == NULL) + goto free_list; + + content = mailmime_content_new(mime_type, subtype, list); + if (content == NULL) + goto free_subtype; + + return content; + + free_subtype: + free(subtype); + free_list: + clist_free(list); + free_type: + mailmime_type_free(mime_type); + free_discrete: + if (discrete_type != NULL) + mailmime_discrete_type_free(discrete_type); + err: + return NULL; +} + + + + + + + + +/* mailmime build */ + + +#if 0 +struct mailmime * +mailmime_new_message_file(char * filename) +{ + struct mailmime_content * content; + struct mailmime * build_info; + struct mailmime_data * msg_content; + struct mailmime_fields * mime_fields; + + content = mailmime_get_content_message(); + if (content == NULL) { + goto err; + } + + mime_fields = mailmime_fields_new_with_version(NULL, NULL, + NULL, NULL, NULL); + if (mime_fields == NULL) + goto free_content; + + msg_content = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT, + 1, NULL, 0, filename); + if (msg_content == NULL) + goto free_fields; + + build_info = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, mime_fields, content, + msg_content, NULL, NULL, NULL, NULL, NULL); + if (build_info == NULL) + goto free_msg_content; + + return build_info; + + free_msg_content: + mailmime_data_free(msg_content); + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return NULL; +} + +struct mailmime * +mailmime_new_message_text(char * data_str, size_t length) +{ + struct mailmime_content * content; + struct mailmime * build_info; + struct mailmime_data * msg_content; + struct mailmime_fields * mime_fields; + + content = mailmime_get_content_message(); + if (content == NULL) { + goto err; + } + + mime_fields = mailmime_fields_new_with_version(NULL, NULL, + NULL, NULL, NULL); + if (mime_fields == NULL) + goto free_fields; + + msg_content = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, + 1, data_str, length, NULL); + if (msg_content == NULL) + goto free_content; + + build_info = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, mime_fields, content, + msg_content, NULL, NULL, NULL, + NULL, NULL); + if (build_info == NULL) + goto free_msg_content; + + return build_info; + + free_msg_content: + mailmime_data_free(msg_content); + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return NULL; +} +#endif + +struct mailmime * +mailmime_new_message_data(struct mailmime * msg_mime) +{ + struct mailmime_content * content; + struct mailmime * build_info; + struct mailmime_fields * mime_fields; + + content = mailmime_get_content_message(); + if (content == NULL) + goto err; + + mime_fields = mailmime_fields_new_with_version(NULL, NULL, + NULL, NULL, NULL); + if (mime_fields == NULL) + goto free_content; + + build_info = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, mime_fields, content, + NULL, NULL, NULL, NULL, + NULL, msg_mime); + if (build_info == NULL) + goto free_fields; + + return build_info; + + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return NULL; +} + +#define MAX_MESSAGE_ID 512 + +static char * generate_boundary() +{ + char id[MAX_MESSAGE_ID]; + time_t now; + char name[MAX_MESSAGE_ID]; + long value; + + now = time(NULL); + value = random(); + + gethostname(name, MAX_MESSAGE_ID); + snprintf(id, MAX_MESSAGE_ID, "%lx_%lx_%x", now, value, getpid()); + + return strdup(id); +} + +struct mailmime * +mailmime_new_empty(struct mailmime_content * content, + struct mailmime_fields * mime_fields) +{ + struct mailmime * build_info; + clist * list; + int r; + int mime_type; + + list = NULL; + + switch (content->ct_type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mime_type = MAILMIME_SINGLE; + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + switch (content->ct_type->tp_data.tp_composite_type->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + mime_type = MAILMIME_MULTIPLE; + break; + + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + if (strcasecmp(content->ct_subtype, "rfc822") == 0) + mime_type = MAILMIME_MESSAGE; + else + mime_type = MAILMIME_SINGLE; + break; + + default: + goto err; + } + break; + + default: + goto err; + } + + if (mime_type == MAILMIME_MULTIPLE) { + char * attr_name; + char * attr_value; + struct mailmime_parameter * param; + clist * parameters; + char * boundary; + + list = clist_new(); + if (list == NULL) + goto err; + + attr_name = strdup("boundary"); + if (attr_name == NULL) + goto free_list; + + boundary = generate_boundary(); + attr_value = boundary; + if (attr_name == NULL) { + free(attr_name); + goto free_list; + } + + param = mailmime_parameter_new(attr_name, attr_value); + if (param == NULL) { + free(attr_value); + free(attr_name); + goto free_list; + } + + if (content->ct_parameters == NULL) { + parameters = clist_new(); + if (parameters == NULL) { + mailmime_parameter_free(param); + goto free_list; + } + } + else + parameters = content->ct_parameters; + + r = clist_append(parameters, param); + if (r != 0) { + clist_free(parameters); + mailmime_parameter_free(param); + goto free_list; + } + + if (content->ct_parameters == NULL) + content->ct_parameters = parameters; + } + + build_info = mailmime_new(mime_type, + NULL, 0, mime_fields, content, + NULL, NULL, NULL, list, + NULL, NULL); + if (build_info == NULL) { + clist_free(list); + return NULL; + } + + return build_info; + + free_list: + clist_free(list); + err: + return NULL; +} + + +int +mailmime_new_with_content(const char * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result) +{ + int r; + size_t cur_token; + struct mailmime_content * content; + struct mailmime * build_info; +#if 0 + int mime_type; +#endif + int res; + + cur_token = 0; + r = mailmime_content_parse(content_type, strlen(content_type), + &cur_token, + &content); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + +#if 0 + switch (content->type->type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mime_type = MAILMIME_SINGLE; + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + switch (content->type->composite_type->type) { + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + mime_type = MAILMIME_MULTIPLE; + break; + + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + if (strcasecmp(content->subtype, "rfc822") == 0) + mime_type = MAILMIME_MESSAGE; + else + mime_type = MAILMIME_SINGLE; + break; + + default: + res = MAILIMF_ERROR_INVAL; + goto free; + } + break; + + default: + res = MAILIMF_ERROR_INVAL; + goto free; + } +#endif + + build_info = mailmime_new_empty(content, mime_fields); + if (build_info == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = build_info; + + return MAILIMF_NO_ERROR; + + free: + mailmime_content_free(content); + err: + return res; +} + +int mailmime_set_preamble_file(struct mailmime * build_info, + char * filename) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT, + 0, NULL, 0, filename); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_preamble = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_epilogue_file(struct mailmime * build_info, + char * filename) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT, + 0, NULL, 0, filename); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_epilogue = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_preamble_text(struct mailmime * build_info, + char * data_str, size_t length) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, + 0, data_str, length, NULL); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_preamble = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_epilogue_text(struct mailmime * build_info, + char * data_str, size_t length) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, + 0, data_str, length, NULL); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_epilogue = data; + + return MAILIMF_NO_ERROR; +} + + +int mailmime_set_body_file(struct mailmime * build_info, + char * filename) +{ + int encoding; + struct mailmime_data * data; + + encoding = mailmime_transfer_encoding_get(build_info->mm_mime_fields); + + data = mailmime_data_new(MAILMIME_DATA_FILE, encoding, + 0, NULL, 0, filename); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_single = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_body_text(struct mailmime * build_info, + char * data_str, size_t length) +{ + int encoding; + struct mailmime_data * data; + + encoding = mailmime_transfer_encoding_get(build_info->mm_mime_fields); + + data = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, + 0, data_str, length, NULL); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_single = data; + + return MAILIMF_NO_ERROR; +} + + +/* add a part as subpart of a mime part */ + +int mailmime_add_part(struct mailmime * build_info, + struct mailmime * part) +{ + int r; + + if (build_info->mm_type == MAILMIME_MESSAGE) { + build_info->mm_data.mm_message.mm_msg_mime = part; + part->mm_parent_type = MAILMIME_MESSAGE; + part->mm_parent = build_info; + } + else if (build_info->mm_type == MAILMIME_MULTIPLE) { + r = clist_append(build_info->mm_data.mm_multipart.mm_mp_list, part); + if (r != 0) + return MAILIMF_ERROR_MEMORY; + + part->mm_parent_type = MAILMIME_MULTIPLE; + part->mm_parent = build_info; + part->mm_multipart_pos = + clist_end(build_info->mm_data.mm_multipart.mm_mp_list); + } + else { + return MAILIMF_ERROR_INVAL; + } + return MAILIMF_NO_ERROR; +} + +/* detach part from parent */ + +void mailmime_remove_part(struct mailmime * mime) +{ + struct mailmime * parent; + + parent = mime->mm_parent; + if (parent == NULL) + return; + + switch (mime->mm_parent_type) { + case MAILMIME_MESSAGE: + mime->mm_parent = NULL; + parent->mm_data.mm_message.mm_msg_mime = NULL; + break; + + case MAILMIME_MULTIPLE: + mime->mm_parent = NULL; + clist_delete(parent->mm_data.mm_multipart.mm_mp_list, + mime->mm_multipart_pos); + break; + } +} + + +/* + attach a part to a mime part and create multipart/mixed + when needed, when the parent part has already some part + attached to it. +*/ + +int mailmime_smart_add_part(struct mailmime * mime, + struct mailmime * mime_sub) +{ + struct mailmime * saved_sub; + struct mailmime * mp; + int res; + int r; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + res = MAILIMF_ERROR_INVAL; + goto err; + + case MAILMIME_MULTIPLE: + r = mailmime_add_part(mime, mime_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + return MAILIMF_NO_ERROR; + } + + /* MAILMIME_MESSAGE */ + + if (mime->mm_data.mm_message.mm_msg_mime == NULL) { + /* there is no subpart, we can simply attach it */ + + r = mailmime_add_part(mime, mime_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + return MAILIMF_NO_ERROR; + } + + if (mime->mm_data.mm_message.mm_msg_mime->mm_type == MAILMIME_MULTIPLE) { + /* in case the subpart is multipart, simply attach it to the subpart */ + + return mailmime_add_part(mime->mm_data.mm_message.mm_msg_mime, mime_sub); + } + + /* we save the current subpart, ... */ + + saved_sub = mime->mm_data.mm_message.mm_msg_mime; + + /* create a multipart */ + + mp = mailmime_multiple_new("multipart/mixed"); + if (mp == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + /* detach the saved subpart from the parent */ + + mailmime_remove_part(saved_sub); + + /* the created multipart is the new child of the parent */ + + r = mailmime_add_part(mime, mp); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto free_mp; + } + + /* then, attach the saved subpart and ... */ + + r = mailmime_add_part(mp, saved_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto free_saved_sub; + } + + /* the given part to the parent */ + + r = mailmime_add_part(mp, mime_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto free_saved_sub; + } + + return MAILIMF_NO_ERROR; + + free_mp: + mailmime_free(mp); + free_saved_sub: + mailmime_free(saved_sub); + err: + return res; +} + + + +/* detach part from parent and free it only if the part has no child */ + +int mailmime_smart_remove_part(struct mailmime * mime) +{ + struct mailmime * parent; + int res; + + parent = mime->mm_parent; + if (parent == NULL) { + res = MAILIMF_ERROR_INVAL; + goto err; + } + + switch (mime->mm_type) { + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + res = MAILIMF_ERROR_INVAL; + goto err; + } + + mailmime_remove_part(mime); + + mailmime_free(mime); + + return MAILIMF_NO_ERROR; + + case MAILMIME_MULTIPLE: + if (!clist_isempty(mime->mm_data.mm_multipart.mm_mp_list)) { + res = MAILIMF_ERROR_INVAL; + goto err; + } + + mailmime_remove_part(mime); + + mailmime_free(mime); + + return MAILIMF_NO_ERROR; + + case MAILMIME_SINGLE: + mailmime_remove_part(mime); + + mailmime_free(mime); + + return MAILIMF_NO_ERROR; + + default: + return MAILIMF_ERROR_INVAL; + } + + err: + return res; +} + + +/* create a mailmime_content structure (Content-Type field) */ + +struct mailmime_content * mailmime_content_new_with_str(const char * str) +{ + int r; + size_t cur_token; + struct mailmime_content * content; + + cur_token = 0; + r = mailmime_content_parse(str, strlen(str), &cur_token, &content); + if (r != MAILIMF_NO_ERROR) + return NULL; + + return content; +} + +/* create MIME fields with only the field Content-Transfer-Encoding */ + +struct mailmime_fields * mailmime_fields_new_encoding(int type) +{ + struct mailmime_mechanism * encoding; + struct mailmime_fields * mime_fields; + + encoding = mailmime_mechanism_new(type, NULL); + if (encoding == NULL) + goto err; + + mime_fields = mailmime_fields_new_with_data(encoding, + NULL, NULL, NULL, NULL); + if (mime_fields == NULL) + goto free; + + return mime_fields; + + free: + mailmime_mechanism_free(encoding); + err: + return NULL; +} + + +/* create a multipart MIME part */ + +struct mailmime * mailmime_multiple_new(const char * type) +{ + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + struct mailmime * mp; + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT); + if (mime_fields == NULL) + goto err; + + content = mailmime_content_new_with_str(type); + if (content == NULL) + goto free_fields; + + mp = mailmime_new_empty(content, mime_fields); + if (mp == NULL) + goto free_content; + + return mp; + + free_content: + mailmime_content_free(content); + free_fields: + mailmime_fields_free(mime_fields); + err: + return NULL; +} + + + +void mailmime_set_imf_fields(struct mailmime * build_info, + struct mailimf_fields * mm_fields) +{ + build_info->mm_data.mm_message.mm_fields = mm_fields; +} + +#if 0 +struct mailmime_content * mailmime_get_content(char * mime_type) +{ + struct mailmime_content *content; + int r; + size_t cur_token; + + cur_token = 0; + r = mailmime_content_parse(mime_type, strlen(mime_type), + &cur_token, &content); + if (r != MAILIMF_NO_ERROR) + return NULL; + + return content; +} +#endif + + + + +struct mailmime_disposition * +mailmime_disposition_new_with_data(int type, + char * filename, char * creation_date, char * modification_date, + char * read_date, size_t size) +{ + struct mailmime_disposition_type * dsp_type; + clist * list; + int r; + struct mailmime_disposition_parm * parm; + struct mailmime_disposition * dsp; + + dsp_type = mailmime_disposition_type_new(type, NULL); + if (dsp_type == NULL) + goto err; + + list = clist_new(); + if (list == NULL) + goto free_dsp_type; + + if (filename != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME, + filename, NULL, NULL, NULL, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (creation_date != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_CREATION_DATE, + NULL, creation_date, NULL, NULL, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (modification_date != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, + NULL, NULL, modification_date, NULL, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (read_date != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_READ_DATE, + NULL, NULL, NULL, read_date, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (size != (size_t) -1) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_SIZE, + NULL, NULL, NULL, NULL, size, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + dsp = mailmime_disposition_new(dsp_type, list); + + return dsp; + + free_list: + clist_foreach(list, (clist_func) mailmime_disposition_parm_free, NULL); + clist_free(list); + free_dsp_type: + mailmime_disposition_type_free(dsp_type); + err: + return NULL; +} + + +static void mailmime_disposition_single_fields_init(struct + mailmime_single_fields * single_fields, + struct mailmime_disposition * fld_disposition) +{ + clistiter * cur; + + single_fields->fld_disposition = fld_disposition; + + for(cur = clist_begin(fld_disposition->dsp_parms) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_disposition_parm * param; + + param = clist_content(cur); + + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + single_fields->fld_disposition_filename = param->pa_data.pa_filename; + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + single_fields->fld_disposition_creation_date = + param->pa_data.pa_creation_date; + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + single_fields->fld_disposition_modification_date = + param->pa_data.pa_modification_date; + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + single_fields->fld_disposition_read_date = + param->pa_data.pa_read_date; + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + single_fields->fld_disposition_size = param->pa_data.pa_size; + break; + } + } +} + +static void mailmime_content_single_fields_init(struct + mailmime_single_fields * single_fields, + struct mailmime_content * fld_content) +{ + clistiter * cur; + + single_fields->fld_content = fld_content; + + for(cur = clist_begin(fld_content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + + if (strcasecmp(param->pa_name, "boundary") == 0) + single_fields->fld_content_boundary = param->pa_value; + + if (strcasecmp(param->pa_name, "charset") == 0) + single_fields->fld_content_charset = param->pa_value; + + if (strcasecmp(param->pa_name, "name") == 0) + single_fields->fld_content_name = param->pa_value; + } +} + +void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, + struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content) +{ + clistiter * cur; + + memset(single_fields, 0, sizeof(struct mailmime_single_fields)); + + if (fld_content != NULL) + mailmime_content_single_fields_init(single_fields, fld_content); + + if (fld_fields == NULL) + return; + + for(cur = clist_begin(fld_fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + mailmime_content_single_fields_init(single_fields, + field->fld_data.fld_content); + break; + + case MAILMIME_FIELD_TRANSFER_ENCODING: + single_fields->fld_encoding = field->fld_data.fld_encoding; + break; + + case MAILMIME_FIELD_ID: + single_fields->fld_id = field->fld_data.fld_id; + break; + + case MAILMIME_FIELD_DESCRIPTION: + single_fields->fld_description = field->fld_data.fld_description; + break; + + case MAILMIME_FIELD_VERSION: + single_fields->fld_version = field->fld_data.fld_version; + break; + + case MAILMIME_FIELD_DISPOSITION: + mailmime_disposition_single_fields_init(single_fields, + field->fld_data.fld_disposition); + break; + + case MAILMIME_FIELD_LANGUAGE: + single_fields->fld_language = field->fld_data.fld_language; + break; + } + } +} + +struct mailmime_single_fields * +mailmime_single_fields_new(struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content) +{ + struct mailmime_single_fields * single_fields; + + single_fields = malloc(sizeof(struct mailmime_single_fields)); + if (single_fields == NULL) + goto err; + + mailmime_single_fields_init(single_fields, fld_fields, fld_content); + + return single_fields; + + err: + return NULL; +} + + +void mailmime_single_fields_free(struct mailmime_single_fields * + single_fields) +{ + free(single_fields); +} + +struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, + char * filename, int encoding_type) +{ + struct mailmime_disposition * dsp; + struct mailmime_mechanism * encoding; + struct mailmime_fields * mime_fields; + + dsp = mailmime_disposition_new_with_data(dsp_type, + filename, NULL, NULL, NULL, (size_t) -1); + if (dsp == NULL) + goto err; + + encoding = mailmime_mechanism_new(encoding_type, NULL); + if (encoding == NULL) + goto free_dsp; + + mime_fields = mailmime_fields_new_with_data(encoding, + NULL, NULL, dsp, NULL); + if (mime_fields == NULL) + goto free_encoding; + + return mime_fields; + + free_encoding: + mailmime_encoding_free(encoding); + free_dsp: + mailmime_disposition_free(dsp); + err: + return NULL; +} + +struct mailmime_data * +mailmime_data_new_data(int encoding, int encoded, + const char * data, size_t length) +{ + return mailmime_data_new(MAILMIME_DATA_TEXT, encoding, encoded, data, length, NULL); +} + +struct mailmime_data * +mailmime_data_new_file(int encoding, int encoded, + char * filename) +{ + return mailmime_data_new(MAILMIME_DATA_FILE, encoding, encoded, NULL, 0, filename); +} + Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_types_helper.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_types_helper.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,197 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_types_helper.h,v 1.16 2005/06/01 12:22:19 smarinier Exp $ + */ + +#ifndef MAILMIME_TYPES_HELPER_H + +#define MAILMIME_TYPES_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailmime_types.h> + +LIBETPAN_EXPORT +int mailmime_transfer_encoding_get(struct mailmime_fields * fields); + +LIBETPAN_EXPORT +struct mailmime_disposition * +mailmime_disposition_new_filename(int type, char * filename); + +LIBETPAN_EXPORT +struct mailmime_fields * mailmime_fields_new_empty(void); + +LIBETPAN_EXPORT +int mailmime_fields_add(struct mailmime_fields * fields, + struct mailmime_field * field); + +LIBETPAN_EXPORT +struct mailmime_fields * +mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +LIBETPAN_EXPORT +struct mailmime_fields * +mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +LIBETPAN_EXPORT +struct mailmime_content * mailmime_get_content_message(void); +LIBETPAN_EXPORT +struct mailmime_content * mailmime_get_content_text(void); +/* struct mailmime_content * mailmime_get_content(char * mime_type); */ + +#define mailmime_get_content mailmime_content_new_with_str + +LIBETPAN_EXPORT +struct mailmime_data * +mailmime_data_new_data(int encoding, int encoded, + const char * data, size_t length); + +LIBETPAN_EXPORT +struct mailmime_data * +mailmime_data_new_file(int encoding, int encoded, + char * filename); + +#if 0 +struct mailmime * +mailmime_new_message_file(char * filename); + +struct mailmime * +mailmime_new_message_text(char * data_str, size_t length); +#endif + +LIBETPAN_EXPORT +struct mailmime * +mailmime_new_message_data(struct mailmime * msg_mime); + +LIBETPAN_EXPORT +struct mailmime * +mailmime_new_empty(struct mailmime_content * content, + struct mailmime_fields * mime_fields); + +LIBETPAN_EXPORT +int +mailmime_new_with_content(const char * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result); + +LIBETPAN_EXPORT +int mailmime_set_preamble_file(struct mailmime * build_info, + char * filename); + +LIBETPAN_EXPORT +int mailmime_set_epilogue_file(struct mailmime * build_info, + char * filename); + +LIBETPAN_EXPORT +int mailmime_set_preamble_text(struct mailmime * build_info, + char * data_str, size_t length); + +LIBETPAN_EXPORT +int mailmime_set_epilogue_text(struct mailmime * build_info, + char * data_str, size_t length); + +LIBETPAN_EXPORT +int mailmime_set_body_file(struct mailmime * build_info, + char * filename); + +LIBETPAN_EXPORT +int mailmime_set_body_text(struct mailmime * build_info, + char * data_str, size_t length); + +LIBETPAN_EXPORT +int mailmime_add_part(struct mailmime * build_info, + struct mailmime * part); + +LIBETPAN_EXPORT +void mailmime_remove_part(struct mailmime * mime); + +LIBETPAN_EXPORT +void mailmime_set_imf_fields(struct mailmime * build_info, + struct mailimf_fields * fields); + + +LIBETPAN_EXPORT +struct mailmime_disposition * +mailmime_disposition_new_with_data(int type, + char * filename, char * creation_date, char * modification_date, + char * read_date, size_t size); + +LIBETPAN_EXPORT +void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, + struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +LIBETPAN_EXPORT +struct mailmime_single_fields * +mailmime_single_fields_new(struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +LIBETPAN_EXPORT +void mailmime_single_fields_free(struct mailmime_single_fields * + single_fields); + +LIBETPAN_EXPORT +int mailmime_smart_add_part(struct mailmime * mime, + struct mailmime * mime_sub); + +LIBETPAN_EXPORT +int mailmime_smart_remove_part(struct mailmime * mime); + +LIBETPAN_EXPORT +struct mailmime_content * mailmime_content_new_with_str(const char * str); + +LIBETPAN_EXPORT +struct mailmime_fields * mailmime_fields_new_encoding(int type); + +LIBETPAN_EXPORT +struct mailmime * mailmime_multiple_new(const char * type); + +LIBETPAN_EXPORT +struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, + char * filename, int encoding_type); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1420 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write.c,v 1.25 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmime_write.h" + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/mman.h> + +#include "mailimf_write.h" +#include "mailmime_content.h" +#include "mailmime_types_helper.h" + +#define MAX_MAIL_COL 78 + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +static int mailmime_field_write(FILE * f, int * col, + struct mailmime_field * field); + +static int mailmime_id_write(FILE * f, int * col, char * id); + +static int mailmime_description_write(FILE * f, int * col, char * descr); + +static int mailmime_version_write(FILE * f, int * col, uint32_t version); + +static int mailmime_encoding_write(FILE * f, int * col, + struct mailmime_mechanism * encoding); + +static int mailmime_language_write(FILE * f, int * col, + struct mailmime_language * language); + +static int mailmime_disposition_write(FILE * f, int * col, + struct mailmime_disposition * + disposition); + +static int +mailmime_disposition_param_write(FILE * f, int * col, + struct mailmime_disposition_parm * param); + +static int mailmime_parameter_write(FILE * f, int * col, + struct mailmime_parameter * param); + +/* +static int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); +*/ + +static int mailmime_type_write(FILE * f, int * col, + struct mailmime_type * type); + +static int +mailmime_discrete_type_write(FILE * f, int * col, + struct mailmime_discrete_type * discrete_type); + +static int +mailmime_composite_type_write(FILE * f, int * col, + struct mailmime_composite_type * composite_type); + +static int mailmime_sub_write(FILE * f, int * col, + struct mailmime * build_info); + + +/* ***** */ + +int mailmime_fields_write(FILE * f, int * col, struct mailmime_fields * fields) +{ + int r; + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = cur->data; + r = mailmime_field_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + +static int mailmime_field_write(FILE * f, int * col, + struct mailmime_field * field) +{ + int r; + + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + r = mailmime_content_write(f, col, field->fld_data.fld_content); + break; + + case MAILMIME_FIELD_TRANSFER_ENCODING: + r = mailmime_encoding_write(f, col, field->fld_data.fld_encoding); + break; + + case MAILMIME_FIELD_ID: + r = mailmime_id_write(f, col, field->fld_data.fld_id); + break; + + case MAILMIME_FIELD_DESCRIPTION: + r = mailmime_description_write(f, col, field->fld_data.fld_description); + break; + + case MAILMIME_FIELD_VERSION: + r = mailmime_version_write(f, col, field->fld_data.fld_version); + break; + + case MAILMIME_FIELD_DISPOSITION: + r = mailmime_disposition_write(f, col, field->fld_data.fld_disposition); + break; + + case MAILMIME_FIELD_LANGUAGE: + r = mailmime_language_write(f, col, field->fld_data.fld_language); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_id_write(FILE * f, int * col, char * id) +{ + int r; + + r = mailimf_string_write(f, col, "Content-ID: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, id, strlen(id)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_description_write(FILE * f, int * col, char * descr) +{ + int r; + + r = mailimf_string_write(f, col, "Content-Description: ", 21); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, descr, strlen(descr)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_version_write(FILE * f, int * col, uint32_t version) +{ + int r; + char versionstr[40]; + + r = mailimf_string_write(f, col, "MIME-Version: ", 14); + if (r != MAILIMF_NO_ERROR) + return r; + + snprintf(versionstr, 40, "%i.%i", version >> 16, version & 0xFFFF); + + r = mailimf_string_write(f, col, versionstr, strlen(versionstr)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_encoding_write(FILE * f, int * col, + struct mailmime_mechanism * encoding) +{ + int r; + + r = mailimf_string_write(f, col, "Content-Transfer-Encoding: ", 27); + if (r != MAILIMF_NO_ERROR) + return r; + + switch (encoding->enc_type) { + case MAILMIME_MECHANISM_7BIT: + r = mailimf_string_write(f, col, "7bit", 4); + break; + + case MAILMIME_MECHANISM_8BIT: + r = mailimf_string_write(f, col, "8bit", 4); + break; + + case MAILMIME_MECHANISM_BINARY: + r = mailimf_string_write(f, col, "binary", 6); + break; + + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + r = mailimf_string_write(f, col, "quoted-printable", 16); + break; + + case MAILMIME_MECHANISM_BASE64: + r = mailimf_string_write(f, col, "base64", 6); + break; + + case MAILMIME_MECHANISM_TOKEN: + r = mailimf_string_write(f, col, encoding->enc_token, + strlen(encoding->enc_token)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_language_write(FILE * f, int * col, + struct mailmime_language * language) +{ + int r; + clistiter * cur; + int first; + + r = mailimf_string_write(f, col, "Content-Language: ", 18); + if (r != MAILIMF_NO_ERROR) + return r; + + first = TRUE; + + for(cur = clist_begin(language->lg_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * lang; + size_t len; + + lang = clist_content(cur); + len = strlen(lang); + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + if (* col > 1) { + + if (* col + len > MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + + r = mailimf_string_write(f, col, lang, len); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_disposition_write(FILE * f, int * col, + struct mailmime_disposition * + disposition) +{ + struct mailmime_disposition_type * dsp_type; + int r; + clistiter * cur; + + dsp_type = disposition->dsp_type; + + r = mailimf_string_write(f, col, "Content-Disposition: ", 21); + if (r != MAILIMF_NO_ERROR) + return r; + + switch (dsp_type->dsp_type) { + case MAILMIME_DISPOSITION_TYPE_INLINE: + r = mailimf_string_write(f, col, "inline", 6); + break; + + case MAILMIME_DISPOSITION_TYPE_ATTACHMENT: + r = mailimf_string_write(f, col, "attachment", 10); + break; + + case MAILMIME_DISPOSITION_TYPE_EXTENSION: + r = mailimf_string_write(f, col, dsp_type->dsp_extension, + strlen(dsp_type->dsp_extension)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + for(cur = clist_begin(disposition->dsp_parms) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_disposition_parm * param; + + param = cur->data; + + r = mailimf_string_write(f, col, "; ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_disposition_param_write(f, col, param); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_disposition_param_write(FILE * f, int * col, + struct mailmime_disposition_parm * param) +{ + size_t len; + char sizestr[20]; + int r; + + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + len = strlen("filename=") + strlen(param->pa_data.pa_filename); + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + len = strlen("creation-date=") + strlen(param->pa_data.pa_creation_date); + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + len = strlen("modification-date=") + + strlen(param->pa_data.pa_modification_date); + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + len = strlen("read-date=") + strlen(param->pa_data.pa_read_date); + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + snprintf(sizestr, 20, "%lu", (unsigned long) param->pa_data.pa_size); + len = strlen("size=") + strlen(sizestr); + break; + + case MAILMIME_DISPOSITION_PARM_PARAMETER: + len = strlen(param->pa_data.pa_parameter->pa_name) + 1 + + strlen(param->pa_data.pa_parameter->pa_value); + break; + + default: + return MAILIMF_ERROR_INVAL; + } + + if (* col > 1) { + + if (* col + len > MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + r = mailimf_string_write(f, col, "filename=", 9); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write(f, col, + param->pa_data.pa_filename, strlen(param->pa_data.pa_filename)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + r = mailimf_string_write(f, col, "creation-date=", 14); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write(f, col, param->pa_data.pa_creation_date, + strlen(param->pa_data.pa_creation_date)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + r = mailimf_string_write(f, col, "modification-date=", 18); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write(f, col, + param->pa_data.pa_modification_date, + strlen(param->pa_data.pa_modification_date)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + r = mailimf_string_write(f, col, "read-date=", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write(f, col, param->pa_data.pa_read_date, + strlen(param->pa_data.pa_read_date)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + r = mailimf_string_write(f, col, "size=", 5); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, sizestr, strlen(sizestr)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_PARAMETER: + r = mailmime_parameter_write(f, col, param->pa_data.pa_parameter); + if (r != MAILIMF_NO_ERROR) + return r; + break; + } + + return MAILIMF_NO_ERROR; +} + +static int mailmime_parameter_write(FILE * f, int * col, + struct mailmime_parameter * param) +{ + int r; + + r = mailimf_string_write(f, col, param->pa_name, + strlen(param->pa_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "=", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write(f, col, param->pa_value, + strlen(param->pa_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content) +{ + clistiter * cur; + size_t len; + int r; + + r = mailmime_type_write(f, col, content->ct_type); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "/", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, content->ct_subtype, + strlen(content->ct_subtype)); + if (r != MAILIMF_NO_ERROR) + return r; + + if (content->ct_parameters != NULL) { + for(cur = clist_begin(content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = cur->data; + + r = mailimf_string_write(f, col, "; ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + len = strlen(param->pa_name) + 1 + strlen(param->pa_value); + + if (* col > 1) { + + if (* col + len > MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + + r = mailmime_parameter_write(f, col, param); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + return MAILIMF_NO_ERROR; +} + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content) +{ + int r; + + r = mailimf_string_write(f, col, "Content-Type: ", 14); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_content_type_write(f, col, content); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_type_write(FILE * f, int * col, + struct mailmime_type * type) +{ + int r; + + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + r = mailmime_discrete_type_write(f, col, type->tp_data.tp_discrete_type); + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + r = mailmime_composite_type_write(f, col, type->tp_data.tp_composite_type); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_discrete_type_write(FILE * f, int * col, + struct mailmime_discrete_type * discrete_type) +{ + int r; + + switch (discrete_type->dt_type) { + case MAILMIME_DISCRETE_TYPE_TEXT: + r = mailimf_string_write(f, col, "text", 4); + break; + + case MAILMIME_DISCRETE_TYPE_IMAGE: + r = mailimf_string_write(f, col, "image", 5); + break; + + case MAILMIME_DISCRETE_TYPE_AUDIO: + r = mailimf_string_write(f, col, "audio", 5); + break; + + case MAILMIME_DISCRETE_TYPE_VIDEO: + r = mailimf_string_write(f, col, "video", 5); + break; + + case MAILMIME_DISCRETE_TYPE_APPLICATION: + r = mailimf_string_write(f, col, "application", 11); + break; + + case MAILMIME_DISCRETE_TYPE_EXTENSION: + r = mailimf_string_write(f, col, discrete_type->dt_extension, + strlen(discrete_type->dt_extension)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_composite_type_write(FILE * f, int * col, + struct mailmime_composite_type * composite_type) +{ + int r; + + switch (composite_type->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + r = mailimf_string_write(f, col, "message", 7); + break; + + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + r = mailimf_string_write(f, col, "multipart", 9); + break; + + case MAILMIME_COMPOSITE_TYPE_EXTENSION: + r = mailimf_string_write(f, col, composite_type->ct_token, + strlen(composite_type->ct_token)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + + + +/* ****************************************************************** */ +/* message */ + +/* +static int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int is_text); +*/ + +static int mailmime_text_content_write(FILE * f, int * col, int encoding, + int istext, + const char * text, size_t size); + +/* +static int mailmime_base64_write(FILE * f, int * col, + char * text, size_t size); + +static int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + char * text, size_t size); +*/ + +static int mailmime_part_write(FILE * f, int * col, + struct mailmime * build_info) +{ + clistiter * cur; + int first; + int r; + char * boundary; + int istext; + + istext = TRUE; + boundary = NULL; + + if (build_info->mm_content_type != NULL) { + if (build_info->mm_type == MAILMIME_MULTIPLE) { + boundary = mailmime_extract_boundary(build_info->mm_content_type); + if (boundary == NULL) + return MAILIMF_ERROR_INVAL; + } + + if (build_info->mm_content_type->ct_type->tp_type == + MAILMIME_TYPE_DISCRETE_TYPE) { + if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type != + MAILMIME_DISCRETE_TYPE_TEXT) + istext = FALSE; + } + } + + switch (build_info->mm_type) { + case MAILMIME_SINGLE: + + /* 1-part body */ + + if (build_info->mm_data.mm_single != NULL) { + r = mailmime_data_write(f, col, build_info->mm_data.mm_single, istext); + if (r != MAILIMF_NO_ERROR) + return r; + } + + break; + + case MAILMIME_MULTIPLE: + + /* multi-part */ + + + /* preamble */ + + if (build_info->mm_data.mm_multipart.mm_preamble != NULL) { + r = mailmime_data_write(f, col, + build_info->mm_data.mm_multipart.mm_preamble, TRUE); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + } + + /* sub-parts */ + + first = TRUE; + + for(cur = clist_begin(build_info->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * subpart; + + subpart = cur->data; + + if (!first) { + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + } + else { + first = FALSE; + } + + r = mailimf_string_write(f, col, "--", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, boundary, strlen(boundary)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + r = mailmime_sub_write(f, col, subpart); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + r = mailimf_string_write(f, col, "--", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, boundary, strlen(boundary)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "--", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + + /* epilogue */ + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + if (build_info->mm_data.mm_multipart.mm_epilogue != NULL) { + r = mailmime_data_write(f, col, + build_info->mm_data.mm_multipart.mm_epilogue, TRUE); + if (r != MAILIMF_NO_ERROR) + return r; + } + + break; + + case MAILMIME_MESSAGE: + + if (build_info->mm_data.mm_message.mm_fields != NULL) { + r = mailimf_fields_write(f, col, + build_info->mm_data.mm_message.mm_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + + if (build_info->mm_mime_fields != NULL) { + r = mailmime_fields_write(f, col, build_info->mm_mime_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + + /* encapsuled message */ + + if (build_info->mm_data.mm_message.mm_msg_mime != NULL) { + r = mailmime_sub_write(f, col, + build_info->mm_data.mm_message.mm_msg_mime); + if (r != MAILIMF_NO_ERROR) + return r; + } + break; + + } + + return MAILIMF_NO_ERROR; +} + + +static int mailmime_sub_write(FILE * f, int * col, + struct mailmime * build_info) +{ + int r; + +#if 0 + * col = 0; +#endif + /* MIME field - Content-Type */ + + if (build_info->mm_content_type != NULL) { + r = mailmime_content_write(f, col, build_info->mm_content_type); + if (r != MAILIMF_NO_ERROR) + return r; + } + + /* other MIME fields */ + + if (build_info->mm_type != MAILMIME_MESSAGE) { + if (build_info->mm_mime_fields != NULL) { + r = mailmime_fields_write(f, col, build_info->mm_mime_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return mailmime_part_write(f, col, build_info); +} + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info) +{ + if (build_info->mm_parent != NULL) + return mailmime_sub_write(f, col, build_info); + else + return mailmime_part_write(f, col, build_info); +} + + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext) +{ + int fd; + int r; + char * text; + struct stat buf; + int res; + + switch (data->dt_type) { + case MAILMIME_DATA_TEXT: + + if (data->dt_encoded) { + r = mailimf_string_write(f, col, + data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + r = mailmime_text_content_write(f, col, data->dt_encoding, istext, + data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length); + if (r != MAILIMF_NO_ERROR) + return r; + } + + break; + + case MAILMIME_DATA_FILE: + fd = open(data->dt_data.dt_filename, O_RDONLY); + if (fd < 0) { + res = MAILIMF_ERROR_FILE; + goto err; + } + + r = fstat(fd, &buf); + if (r < 0) { + res = MAILIMF_ERROR_FILE; + goto close; + } + + if (buf.st_size != 0) { + text = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (text == (char *)MAP_FAILED) { + res = MAILIMF_ERROR_FILE; + goto close; + } + + if (data->dt_encoded) { + r = mailimf_string_write(f, col, text, buf.st_size); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto unmap; + } + } + else { + r = mailmime_text_content_write(f, col, data->dt_encoding, istext, + text, buf.st_size); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto unmap; + } + } + + munmap(text, buf.st_size); + } + close(fd); + + if (r != MAILIMF_NO_ERROR) + return r; + + break; + + unmap: + munmap(text, buf.st_size); + close: + close(fd); + err: + return res; + } + + return MAILIMF_NO_ERROR; +} + +static int mailmime_text_content_write(FILE * f, int * col, int encoding, + int istext, + const char * text, size_t size) +{ + switch (encoding) { + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + return mailmime_quoted_printable_write(f, col, istext, text, size); + break; + + case MAILMIME_MECHANISM_BASE64: + return mailmime_base64_write(f, col, text, size); + break; + + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_BINARY: + default: + return mailimf_string_write(f, col, text, size); + } +} + + +static const char base64_encoding[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +#define BASE64_MAX_COL 76 + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size) +{ + int a; + int b; + int c; + size_t remains; + const char * p; + size_t count; + char ogroup[4]; + int r; + + remains = size; + p = text; + + while (remains > 0) { + switch (remains) { + case 1: + a = (unsigned char) p[0]; + b = 0; + c = 0; + count = 1; + break; + case 2: + a = (unsigned char) p[0]; + b = (unsigned char) p[1]; + c = 0; + count = 2; + break; + default: + a = (unsigned char) p[0]; + b = (unsigned char) p[1]; + c = (unsigned char) p[2]; + count = 3; + break; + } + + ogroup[0]= base64_encoding[a >> 2]; + ogroup[1]= base64_encoding[((a & 3) << 4) | (b >> 4)]; + ogroup[2]= base64_encoding[((b & 0xF) << 2) | (c >> 6)]; + ogroup[3]= base64_encoding[c & 0x3F]; + + switch (count) { + case 1: + ogroup[2]= '='; + ogroup[3]= '='; + break; + case 2: + ogroup[3]= '='; + break; + } + + if (* col + 4 > BASE64_MAX_COL) { + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + } + + r = mailimf_string_write(f, col, ogroup, 4); + if (r != MAILIMF_NO_ERROR) + return r; + + remains -= count; + p += count; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + + return MAILIMF_NO_ERROR; +} + +#if 0 +#define MAX_WRITE_SIZE 512 +#endif + +enum { + STATE_INIT, + STATE_CR, + STATE_SPACE, + STATE_SPACE_CR, +}; + +#if 0 +static inline int write_try_buf(FILE * f, int * col, + char ** pstart, size_t * plen) +{ + int r; + + if (* plen >= MAX_WRITE_SIZE) { + r = mailimf_string_write(f, col, * pstart, * plen); + if (r != MAILIMF_NO_ERROR) + return r; + * plen = 0; + } + + return MAILIMF_NO_ERROR; +} +#endif + +static inline int write_remaining(FILE * f, int * col, + const char ** pstart, size_t * plen) +{ + int r; + + if (* plen > 0) { + r = mailimf_string_write(f, col, * pstart, * plen); + if (r != MAILIMF_NO_ERROR) + return r; + * plen = 0; + } + + return MAILIMF_NO_ERROR; +} + + + +#define QP_MAX_COL 72 + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size) +{ + size_t i; + const char * start; + size_t len; + char hexstr[6]; + int r; + int state; + + start = text; + len = 0; + state = STATE_INIT; + + i = 0; + while (i < size) { + unsigned char ch; + + if (* col + len > QP_MAX_COL) { + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i; + + r = mailimf_string_write(f, col, "=\r\n", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + + ch = text[i]; + + switch (state) { + + case STATE_INIT: + switch (ch) { + case ' ': + case '\t': + state = STATE_SPACE; + break; + + case '\r': + state = STATE_CR; + break; + + case '!': + case '"': + case '#': + case '$': + case '@': + case '[': + case '\\': + case ']': + case '^': + case '`': + case '{': + case '|': + case '}': + case '~': + case '=': + case '?': + case '_': + case 'F': /* there is no more 'From' at the beginning of a line */ + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + + snprintf(hexstr, 6, "=%02X", ch); + + r = mailimf_string_write(f, col, hexstr, 3); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + default: + if (istext && (ch == '\n')) { + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + break; + } + else { + if (((ch >= 33) && (ch <= 60)) || ((ch >= 62) && (ch <= 126))) { + len ++; + } + else { + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + + snprintf(hexstr, 6, "=%02X", ch); + + r = mailimf_string_write(f, col, hexstr, 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + break; + } + + i ++; + break; + + case STATE_CR: + switch (ch) { + case '\n': + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + i ++; + state = STATE_INIT; + break; + + default: + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i; + snprintf(hexstr, 6, "=%02X", '\r'); + r = mailimf_string_write(f, col, hexstr, 3); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + break; + } + break; + + case STATE_SPACE: + switch (ch) { + case '\r': + state = STATE_SPACE_CR; + i ++; + break; + + case '\n': + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + snprintf(hexstr, 6, "=%02X\r\n", text[i - 1]); + r = mailimf_string_write(f, col, hexstr, strlen(hexstr)); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + i ++; + break; + + case ' ': + case '\t': + len ++; + i ++; + break; + + default: +#if 0 + len += 2; + state = STATE_INIT; + i ++; +#endif + len ++; + state = STATE_INIT; + break; + } + + break; + + case STATE_SPACE_CR: + switch (ch) { + case '\n': + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + snprintf(hexstr, 6, "=%02X\r\n", text[i - 2]); + r = mailimf_string_write(f, col, hexstr, strlen(hexstr)); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + i ++; + break; + + default: + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + snprintf(hexstr, 6, "%c=%02X", text[i - 2], '\r'); + r = mailimf_string_write(f, col, hexstr, strlen(hexstr)); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + break; + } + + break; + } + } + + return MAILIMF_NO_ERROR; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,73 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write.h,v 1.13 2004/11/21 21:53:39 hoa Exp $ + */ + +#ifndef MAILMIME_WRITE_H + +#define MAILMIME_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailmime_types.h> +#include <stdio.h> + +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields); + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info); + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size); + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size); + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_file.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_file.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,164 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write_file.c,v 1.5 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmime_write_file.h" + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif + +#include "mailmime_content.h" +#include "mailmime_types_helper.h" +#include "mailmime_write_generic.h" + +static int do_write(void * data, const char * str, size_t length) +{ + FILE * f; + + f = data; + + return fwrite(str, 1, length, f); +} + + +int mailmime_fields_write_file(FILE * f, int * col, + struct mailmime_fields * fields) +{ + return mailmime_fields_write_driver(do_write, f, col, fields); +} + +int mailmime_content_write_file(FILE * f, int * col, + struct mailmime_content * content) +{ + return mailmime_content_write_driver(do_write, f, col, content); +} + +int mailmime_content_type_write_file(FILE * f, int * col, + struct mailmime_content * content) +{ + return mailmime_content_type_write_driver(do_write, f, col, content); +} + +int mailmime_write_file(FILE * f, int * col, + struct mailmime * build_info) +{ + return mailmime_write_driver(do_write, f, col, build_info); +} + +int mailmime_quoted_printable_write_file(FILE * f, int * col, int istext, + const char * text, size_t size) +{ + return mailmime_quoted_printable_write_driver(do_write, f, col, + istext, text, size); +} + +int mailmime_base64_write_file(FILE * f, int * col, + const char * text, size_t size) +{ + return mailmime_base64_write_driver(do_write, f, col, text, size); +} + +int mailmime_data_write_file(FILE * f, int * col, + struct mailmime_data * data, + int istext) +{ + return mailmime_data_write_driver(do_write, f, col, data, istext); +} + + + + +/* binary compatibility with 0.34 - begin */ + +#ifdef MAILMIME_WRITE_COMPATIBILITY +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields) +{ + return mailmime_fields_write_file(f, col, fields); +} + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content) +{ + return mailmime_content_write_file(f, col, content); +} + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content) +{ + return mailmime_content_type_write_file(f, col, content); +} + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info) +{ + return mailmime_write_file(f, col, build_info); +} + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size) +{ + return mailmime_quoted_printable_write_file(f, col, + istext, text, size); +} + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size) +{ + return mailmime_base64_write_file(f, col, text, size); +} + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext) +{ + return mailmime_data_write_file(f, col, data, istext); +} +#endif + +/* binary compatibility with 0.34 - end */ Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_file.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_file.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,118 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write_file.h,v 1.3 2005/06/01 12:22:19 smarinier Exp $ + */ + +#ifndef MAILMIME_WRITE_FILE_H + +#define MAILMIME_WRITE_FILE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailmime_types.h> +#include <stdio.h> + +#define MAILMIME_WRITE_COMPATIBILITY + +LIBETPAN_EXPORT +int mailmime_fields_write_file(FILE * f, int * col, + struct mailmime_fields * fields); + +LIBETPAN_EXPORT +int mailmime_content_write_file(FILE * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_content_type_write_file(FILE * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_write_file(FILE * f, int * col, + struct mailmime * build_info); + +LIBETPAN_EXPORT +int mailmime_quoted_printable_write_file(FILE * f, int * col, int istext, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_base64_write_file(FILE * f, int * col, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_data_write_file(FILE * f, int * col, + struct mailmime_data * data, + int istext); + + +/* binary compatibility with 0.34 - begin */ + +#ifdef MAILMIME_WRITE_COMPATIBILITY +LIBETPAN_EXPORT +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields); + +LIBETPAN_EXPORT +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info); + +LIBETPAN_EXPORT +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext); +#endif + +/* binary compatibility with 0.34 - end */ + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_generic.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_generic.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1427 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write_generic.c,v 1.6 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmime_write_generic.h" + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif +#ifdef _MSC_VER +# include "win_etpan.h" +#endif + +#include "mailimf_write_generic.h" +#include "mailmime_content.h" +#include "mailmime_types_helper.h" + +#define MAX_MAIL_COL 78 + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +static int mailmime_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_field * field); + +static int mailmime_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * id); + +static int mailmime_description_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * descr); + +static int mailmime_version_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, uint32_t version); + +static int mailmime_encoding_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_mechanism * encoding); + +static int mailmime_language_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_language * language); + +static int mailmime_disposition_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_disposition * + disposition); + +static int +mailmime_disposition_param_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_disposition_parm * param); + +static int mailmime_parameter_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_parameter * param); + +/* +static int mailmime_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_content * content); +*/ + +static int mailmime_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_type * type); + +static int +mailmime_discrete_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_discrete_type * discrete_type); + +static int +mailmime_composite_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_composite_type * composite_type); + +static int mailmime_sub_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime * build_info); + + +/* ***** */ + +int mailmime_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, struct mailmime_fields * fields) +{ + int r; + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = cur->data; + r = mailmime_field_write_driver(do_write, data, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + +static int mailmime_field_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_field * field) +{ + int r; + + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + r = mailmime_content_write_driver(do_write, data, col, field->fld_data.fld_content); + break; + + case MAILMIME_FIELD_TRANSFER_ENCODING: + r = mailmime_encoding_write_driver(do_write, data, col, field->fld_data.fld_encoding); + break; + + case MAILMIME_FIELD_ID: + r = mailmime_id_write_driver(do_write, data, col, field->fld_data.fld_id); + break; + + case MAILMIME_FIELD_DESCRIPTION: + r = mailmime_description_write_driver(do_write, data, col, field->fld_data.fld_description); + break; + + case MAILMIME_FIELD_VERSION: + r = mailmime_version_write_driver(do_write, data, col, field->fld_data.fld_version); + break; + + case MAILMIME_FIELD_DISPOSITION: + r = mailmime_disposition_write_driver(do_write, data, col, field->fld_data.fld_disposition); + break; + + case MAILMIME_FIELD_LANGUAGE: + r = mailmime_language_write_driver(do_write, data, col, field->fld_data.fld_language); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * id) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Content-ID: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, id, strlen(id)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_description_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * descr) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Content-Description: ", 21); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, descr, strlen(descr)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_version_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, uint32_t version) +{ + int r; + char versionstr[40]; + + r = mailimf_string_write_driver(do_write, data, col, "MIME-Version: ", 14); + if (r != MAILIMF_NO_ERROR) + return r; + + snprintf(versionstr, 40, "%i.%i", version >> 16, version & 0xFFFF); + + r = mailimf_string_write_driver(do_write, data, col, versionstr, strlen(versionstr)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_encoding_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_mechanism * encoding) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Content-Transfer-Encoding: ", 27); + if (r != MAILIMF_NO_ERROR) + return r; + + switch (encoding->enc_type) { + case MAILMIME_MECHANISM_7BIT: + r = mailimf_string_write_driver(do_write, data, col, "7bit", 4); + break; + + case MAILMIME_MECHANISM_8BIT: + r = mailimf_string_write_driver(do_write, data, col, "8bit", 4); + break; + + case MAILMIME_MECHANISM_BINARY: + r = mailimf_string_write_driver(do_write, data, col, "binary", 6); + break; + + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + r = mailimf_string_write_driver(do_write, data, col, "quoted-printable", 16); + break; + + case MAILMIME_MECHANISM_BASE64: + r = mailimf_string_write_driver(do_write, data, col, "base64", 6); + break; + + case MAILMIME_MECHANISM_TOKEN: + r = mailimf_string_write_driver(do_write, data, col, encoding->enc_token, + strlen(encoding->enc_token)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_language_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_language * language) +{ + int r; + clistiter * cur; + int first; + + r = mailimf_string_write_driver(do_write, data, col, "Content-Language: ", 18); + if (r != MAILIMF_NO_ERROR) + return r; + + first = TRUE; + + for(cur = clist_begin(language->lg_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * lang; + size_t len; + + lang = clist_content(cur); + len = strlen(lang); + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + if (* col > 1) { + + if (* col + len > MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + + r = mailimf_string_write_driver(do_write, data, col, lang, len); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_disposition_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_disposition * + disposition) +{ + struct mailmime_disposition_type * dsp_type; + int r; + clistiter * cur; + + dsp_type = disposition->dsp_type; + + r = mailimf_string_write_driver(do_write, data, col, "Content-Disposition: ", 21); + if (r != MAILIMF_NO_ERROR) + return r; + + switch (dsp_type->dsp_type) { + case MAILMIME_DISPOSITION_TYPE_INLINE: + r = mailimf_string_write_driver(do_write, data, col, "inline", 6); + break; + + case MAILMIME_DISPOSITION_TYPE_ATTACHMENT: + r = mailimf_string_write_driver(do_write, data, col, "attachment", 10); + break; + + case MAILMIME_DISPOSITION_TYPE_EXTENSION: + r = mailimf_string_write_driver(do_write, data, col, dsp_type->dsp_extension, + strlen(dsp_type->dsp_extension)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + for(cur = clist_begin(disposition->dsp_parms) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_disposition_parm * param; + + param = cur->data; + + r = mailimf_string_write_driver(do_write, data, col, "; ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_disposition_param_write_driver(do_write, data, col, param); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_disposition_param_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_disposition_parm * param) +{ + size_t len; + char sizestr[20]; + int r; + + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + len = strlen("filename=") + strlen(param->pa_data.pa_filename); + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + len = strlen("creation-date=") + strlen(param->pa_data.pa_creation_date); + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + len = strlen("modification-date=") + + strlen(param->pa_data.pa_modification_date); + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + len = strlen("read-date=") + strlen(param->pa_data.pa_read_date); + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + snprintf(sizestr, 20, "%lu", (unsigned long) param->pa_data.pa_size); + len = strlen("size=") + strlen(sizestr); + break; + + case MAILMIME_DISPOSITION_PARM_PARAMETER: + len = strlen(param->pa_data.pa_parameter->pa_name) + 1 + + strlen(param->pa_data.pa_parameter->pa_value); + break; + + default: + return MAILIMF_ERROR_INVAL; + } + + if (* col > 1) { + + if (* col + len > MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + r = mailimf_string_write_driver(do_write, data, col, "filename=", 9); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write_driver(do_write, data, col, + param->pa_data.pa_filename, strlen(param->pa_data.pa_filename)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + r = mailimf_string_write_driver(do_write, data, col, "creation-date=", 14); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write_driver(do_write, data, col, param->pa_data.pa_creation_date, + strlen(param->pa_data.pa_creation_date)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + r = mailimf_string_write_driver(do_write, data, col, "modification-date=", 18); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write_driver(do_write, data, col, + param->pa_data.pa_modification_date, + strlen(param->pa_data.pa_modification_date)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + r = mailimf_string_write_driver(do_write, data, col, "read-date=", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write_driver(do_write, data, col, param->pa_data.pa_read_date, + strlen(param->pa_data.pa_read_date)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + r = mailimf_string_write_driver(do_write, data, col, "size=", 5); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, sizestr, strlen(sizestr)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_PARAMETER: + r = mailmime_parameter_write_driver(do_write, data, col, param->pa_data.pa_parameter); + if (r != MAILIMF_NO_ERROR) + return r; + break; + } + + return MAILIMF_NO_ERROR; +} + +static int mailmime_parameter_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_parameter * param) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, param->pa_name, + strlen(param->pa_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "=", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write_driver(do_write, data, col, param->pa_value, + strlen(param->pa_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +int mailmime_content_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_content * content) +{ + clistiter * cur; + size_t len; + int r; + + r = mailmime_type_write_driver(do_write, data, col, content->ct_type); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "/", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, content->ct_subtype, + strlen(content->ct_subtype)); + if (r != MAILIMF_NO_ERROR) + return r; + + if (content->ct_parameters != NULL) { + for(cur = clist_begin(content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = cur->data; + + r = mailimf_string_write_driver(do_write, data, col, "; ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + len = strlen(param->pa_name) + 1 + strlen(param->pa_value); + + if (* col > 1) { + + if (* col + len > MAX_MAIL_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + + r = mailmime_parameter_write_driver(do_write, data, col, param); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + return MAILIMF_NO_ERROR; +} + +int mailmime_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_content * content) +{ + int r; + + r = mailimf_string_write_driver(do_write, data, col, "Content-Type: ", 14); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_content_type_write_driver(do_write, data, col, content); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_type * type) +{ + int r; + + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + r = mailmime_discrete_type_write_driver(do_write, data, col, type->tp_data.tp_discrete_type); + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + r = mailmime_composite_type_write_driver(do_write, data, col, type->tp_data.tp_composite_type); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_discrete_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_discrete_type * discrete_type) +{ + int r; + + switch (discrete_type->dt_type) { + case MAILMIME_DISCRETE_TYPE_TEXT: + r = mailimf_string_write_driver(do_write, data, col, "text", 4); + break; + + case MAILMIME_DISCRETE_TYPE_IMAGE: + r = mailimf_string_write_driver(do_write, data, col, "image", 5); + break; + + case MAILMIME_DISCRETE_TYPE_AUDIO: + r = mailimf_string_write_driver(do_write, data, col, "audio", 5); + break; + + case MAILMIME_DISCRETE_TYPE_VIDEO: + r = mailimf_string_write_driver(do_write, data, col, "video", 5); + break; + + case MAILMIME_DISCRETE_TYPE_APPLICATION: + r = mailimf_string_write_driver(do_write, data, col, "application", 11); + break; + + case MAILMIME_DISCRETE_TYPE_EXTENSION: + r = mailimf_string_write_driver(do_write, data, col, discrete_type->dt_extension, + strlen(discrete_type->dt_extension)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_composite_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_composite_type * composite_type) +{ + int r; + + switch (composite_type->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + r = mailimf_string_write_driver(do_write, data, col, "message", 7); + break; + + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + r = mailimf_string_write_driver(do_write, data, col, "multipart", 9); + break; + + case MAILMIME_COMPOSITE_TYPE_EXTENSION: + r = mailimf_string_write_driver(do_write, data, col, composite_type->ct_token, + strlen(composite_type->ct_token)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + + + +/* ****************************************************************** */ +/* message */ + +/* +static int mailmime_data_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_data * data, + int is_text); +*/ + +static int mailmime_text_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int encoding, + int istext, + const char * text, size_t size); + +/* +static int mailmime_base64_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + char * text, size_t size); + +static int mailmime_quoted_printable_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int istext, + char * text, size_t size); +*/ + +static int mailmime_part_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime * build_info) +{ + clistiter * cur; + int first; + int r; + char * boundary; + int istext; + + istext = TRUE; + boundary = NULL; + + if (build_info->mm_content_type != NULL) { + if (build_info->mm_type == MAILMIME_MULTIPLE) { + boundary = mailmime_extract_boundary(build_info->mm_content_type); + if (boundary == NULL) + return MAILIMF_ERROR_INVAL; + } + + if (build_info->mm_content_type->ct_type->tp_type == + MAILMIME_TYPE_DISCRETE_TYPE) { + if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type != + MAILMIME_DISCRETE_TYPE_TEXT) + istext = FALSE; + } + } + + switch (build_info->mm_type) { + case MAILMIME_SINGLE: + + /* 1-part body */ + + if (build_info->mm_data.mm_single != NULL) { + r = mailmime_data_write_driver(do_write, data, col, build_info->mm_data.mm_single, istext); + if (r != MAILIMF_NO_ERROR) + return r; + } + + break; + + case MAILMIME_MULTIPLE: + + /* multi-part */ + + + /* preamble */ + + if (build_info->mm_data.mm_multipart.mm_preamble != NULL) { + r = mailmime_data_write_driver(do_write, data, col, + build_info->mm_data.mm_multipart.mm_preamble, TRUE); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + } + + /* sub-parts */ + + first = TRUE; + + for(cur = clist_begin(build_info->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * subpart; + + subpart = cur->data; + + if (!first) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + } + else { + first = FALSE; + } + + r = mailimf_string_write_driver(do_write, data, col, "--", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, boundary, strlen(boundary)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + r = mailmime_sub_write_driver(do_write, data, col, subpart); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + r = mailimf_string_write_driver(do_write, data, col, "--", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, boundary, strlen(boundary)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write_driver(do_write, data, col, "--", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + + /* epilogue */ + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + if (build_info->mm_data.mm_multipart.mm_epilogue != NULL) { + r = mailmime_data_write_driver(do_write, data, col, + build_info->mm_data.mm_multipart.mm_epilogue, TRUE); + if (r != MAILIMF_NO_ERROR) + return r; + } + + break; + + case MAILMIME_MESSAGE: + + if (build_info->mm_data.mm_message.mm_fields != NULL) { + r = mailimf_fields_write_driver(do_write, data, col, + build_info->mm_data.mm_message.mm_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + + if (build_info->mm_mime_fields != NULL) { + r = mailmime_fields_write_driver(do_write, data, col, build_info->mm_mime_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + + /* encapsuled message */ + + if (build_info->mm_data.mm_message.mm_msg_mime != NULL) { + r = mailmime_sub_write_driver(do_write, data, col, + build_info->mm_data.mm_message.mm_msg_mime); + if (r != MAILIMF_NO_ERROR) + return r; + } + break; + + } + + return MAILIMF_NO_ERROR; +} + + +static int mailmime_sub_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime * build_info) +{ + int r; + +#if 0 + * col = 0; +#endif + /* MIME field - Content-Type */ + + if (build_info->mm_content_type != NULL) { + r = mailmime_content_write_driver(do_write, data, col, build_info->mm_content_type); + if (r != MAILIMF_NO_ERROR) + return r; + } + + /* other MIME fields */ + + if (build_info->mm_type != MAILMIME_MESSAGE) { + if (build_info->mm_mime_fields != NULL) { + r = mailmime_fields_write_driver(do_write, data, col, build_info->mm_mime_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return mailmime_part_write_driver(do_write, data, col, build_info); +} + +int mailmime_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime * build_info) +{ + if (build_info->mm_parent != NULL) + return mailmime_sub_write_driver(do_write, data, col, build_info); + else + return mailmime_part_write_driver(do_write, data, col, build_info); +} + + +int mailmime_data_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_data * mime_data, + int istext) +{ + int fd; + int r; + char * text; + struct stat buf; + int res; + + switch (mime_data->dt_type) { + case MAILMIME_DATA_TEXT: + + if (mime_data->dt_encoded) { + r = mailimf_string_write_driver(do_write, data, col, + mime_data->dt_data.dt_text.dt_data, + mime_data->dt_data.dt_text.dt_length); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + r = mailmime_text_content_write_driver(do_write, data, col, mime_data->dt_encoding, istext, + mime_data->dt_data.dt_text.dt_data, + mime_data->dt_data.dt_text.dt_length); + if (r != MAILIMF_NO_ERROR) + return r; + } + + break; + + case MAILMIME_DATA_FILE: + fd = open(mime_data->dt_data.dt_filename, O_RDONLY); + if (fd < 0) { + res = MAILIMF_ERROR_FILE; + goto err; + } + + r = fstat(fd, &buf); + if (r < 0) { + res = MAILIMF_ERROR_FILE; + goto close; + } + + if (buf.st_size != 0) { + text = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (text == (char *)MAP_FAILED) { + res = MAILIMF_ERROR_FILE; + goto close; + } + + if (mime_data->dt_encoded) { + r = mailimf_string_write_driver(do_write, data, col, text, buf.st_size); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto unmap; + } + } + else { + r = mailmime_text_content_write_driver(do_write, data, col, mime_data->dt_encoding, istext, + text, buf.st_size); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto unmap; + } + } + + munmap(text, buf.st_size); + } + close(fd); + + if (r != MAILIMF_NO_ERROR) + return r; + + break; + + unmap: + munmap(text, buf.st_size); + close: + close(fd); + err: + return res; + } + + return MAILIMF_NO_ERROR; +} + +static int mailmime_text_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int encoding, + int istext, + const char * text, size_t size) +{ + switch (encoding) { + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + return mailmime_quoted_printable_write_driver(do_write, data, col, istext, text, size); + break; + + case MAILMIME_MECHANISM_BASE64: + return mailmime_base64_write_driver(do_write, data, col, text, size); + break; + + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_BINARY: + default: + return mailimf_string_write_driver(do_write, data, col, text, size); + } +} + + +static const char base64_encoding[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +#define BASE64_MAX_COL 76 + +int mailmime_base64_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * text, size_t size) +{ + int a; + int b; + int c; + size_t remains; + const char * p; + size_t count; + char ogroup[4]; + int r; + + remains = size; + p = text; + + while (remains > 0) { + switch (remains) { + case 1: + a = (unsigned char) p[0]; + b = 0; + c = 0; + count = 1; + break; + case 2: + a = (unsigned char) p[0]; + b = (unsigned char) p[1]; + c = 0; + count = 2; + break; + default: + a = (unsigned char) p[0]; + b = (unsigned char) p[1]; + c = (unsigned char) p[2]; + count = 3; + break; + } + + ogroup[0]= base64_encoding[a >> 2]; + ogroup[1]= base64_encoding[((a & 3) << 4) | (b >> 4)]; + ogroup[2]= base64_encoding[((b & 0xF) << 2) | (c >> 6)]; + ogroup[3]= base64_encoding[c & 0x3F]; + + switch (count) { + case 1: + ogroup[2]= '='; + ogroup[3]= '='; + break; + case 2: + ogroup[3]= '='; + break; + } + + if (* col + 4 > BASE64_MAX_COL) { + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + } + + r = mailimf_string_write_driver(do_write, data, col, ogroup, 4); + if (r != MAILIMF_NO_ERROR) + return r; + + remains -= count; + p += count; + } + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + + return MAILIMF_NO_ERROR; +} + +#if 0 +#define MAX_WRITE_SIZE 512 +#endif + +enum { + STATE_INIT, + STATE_CR, + STATE_SPACE, + STATE_SPACE_CR +}; + +#if 0 +static inline int write_try_buf(int (* do_write)(void *, const char *, size_t), void * data, int * col, + char ** pstart, size_t * plen) +{ + int r; + + if (* plen >= MAX_WRITE_SIZE) { + r = mailimf_string_write_driver(do_write, data, col, * pstart, * plen); + if (r != MAILIMF_NO_ERROR) + return r; + * plen = 0; + } + + return MAILIMF_NO_ERROR; +} +#endif + +static inline int write_remaining(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char ** pstart, size_t * plen) +{ + int r; + + if (* plen > 0) { + r = mailimf_string_write_driver(do_write, data, col, * pstart, * plen); + if (r != MAILIMF_NO_ERROR) + return r; + * plen = 0; + } + + return MAILIMF_NO_ERROR; +} + + + +#define QP_MAX_COL 72 + +int mailmime_quoted_printable_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int istext, + const char * text, size_t size) +{ + size_t i; + const char * start; + size_t len; + char hexstr[6]; + int r; + int state; + + start = text; + len = 0; + state = STATE_INIT; + + i = 0; + while (i < size) { + unsigned char ch; + + if (* col + len > QP_MAX_COL) { + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i; + + r = mailimf_string_write_driver(do_write, data, col, "=\r\n", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + + ch = text[i]; + + switch (state) { + + case STATE_INIT: + switch (ch) { + case ' ': + case '\t': + state = STATE_SPACE; + break; + + case '\r': + state = STATE_CR; + break; + + case '!': + case '"': + case '#': + case '$': + case '@': + case '[': + case '\\': + case ']': + case '^': + case '`': + case '{': + case '|': + case '}': + case '~': + case '=': + case '?': + case '_': + case 'F': /* there is no more 'From' at the beginning of a line */ + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + + snprintf(hexstr, 6, "=%02X", ch); + + r = mailimf_string_write_driver(do_write, data, col, hexstr, 3); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + default: + if (istext && (ch == '\n')) { + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + break; + } + else { + if (((ch >= 33) && (ch <= 60)) || ((ch >= 62) && (ch <= 126))) { + len ++; + } + else { + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + + snprintf(hexstr, 6, "=%02X", ch); + + r = mailimf_string_write_driver(do_write, data, col, hexstr, 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + break; + } + + i ++; + break; + + case STATE_CR: + switch (ch) { + case '\n': + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + r = mailimf_string_write_driver(do_write, data, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + i ++; + state = STATE_INIT; + break; + + default: + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i; + snprintf(hexstr, 6, "=%02X", '\r'); + r = mailimf_string_write_driver(do_write, data, col, hexstr, 3); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + break; + } + break; + + case STATE_SPACE: + switch (ch) { + case '\r': + state = STATE_SPACE_CR; + i ++; + break; + + case '\n': + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + snprintf(hexstr, 6, "=%02X\r\n", text[i - 1]); + r = mailimf_string_write_driver(do_write, data, col, hexstr, strlen(hexstr)); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + i ++; + break; + + case ' ': + case '\t': + len ++; + i ++; + break; + + default: +#if 0 + len += 2; + state = STATE_INIT; + i ++; +#endif + len ++; + state = STATE_INIT; + break; + } + + break; + + case STATE_SPACE_CR: + switch (ch) { + case '\n': + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + snprintf(hexstr, 6, "=%02X\r\n", text[i - 2]); + r = mailimf_string_write_driver(do_write, data, col, hexstr, strlen(hexstr)); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + i ++; + break; + + default: + r = write_remaining(do_write, data, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + snprintf(hexstr, 6, "%c=%02X", text[i - 2], '\r'); + r = mailimf_string_write_driver(do_write, data, col, hexstr, strlen(hexstr)); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + break; + } + + break; + } + } + + return MAILIMF_NO_ERROR; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_generic.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_generic.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,73 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write_generic.h,v 1.2 2004/11/21 21:53:39 hoa Exp $ + */ + +#ifndef MAILMIME_WRITE_GENERIC_H + +#define MAILMIME_WRITE_GENERIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailmime_types.h> +#include <stdio.h> + +int mailmime_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_fields * fields); + +int mailmime_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_content * content); + +int mailmime_content_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_content * content); + +int mailmime_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime * build_info); + +int mailmime_quoted_printable_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int istext, + const char * text, size_t size); + +int mailmime_base64_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + const char * text, size_t size); + +int mailmime_data_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, + struct mailmime_data * mime_data, + int istext); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_mem.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_mem.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,114 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write_mem.c,v 1.5 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailmime_write_mem.h" + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif + +#include "mailmime_content.h" +#include "mailmime_types_helper.h" +#include "mailmime_write_generic.h" + +static int do_write(void * data, const char * str, size_t length) +{ + MMAPString * f; + + f = data; + + if (mmap_string_append_len(f, str, length) == NULL) + return 0; + else + return length; +} + +int mailmime_fields_write_mem(MMAPString * f, int * col, + struct mailmime_fields * fields) +{ + return mailmime_fields_write_driver(do_write, f, col, fields); +} + +int mailmime_content_write_mem(MMAPString * f, int * col, + struct mailmime_content * content) +{ + return mailmime_content_write_driver(do_write, f, col, content); +} + +int mailmime_content_type_write_mem(MMAPString * f, int * col, + struct mailmime_content * content) +{ + return mailmime_content_type_write_driver(do_write, f, col, content); +} + +int mailmime_write_mem(MMAPString * f, int * col, + struct mailmime * build_info) +{ + return mailmime_write_driver(do_write, f, col, build_info); +} + +int mailmime_quoted_printable_write_mem(MMAPString * f, int * col, int istext, + const char * text, size_t size) +{ + return mailmime_quoted_printable_write_driver(do_write, f, col, + istext, text, size); +} + +int mailmime_base64_write_mem(MMAPString * f, int * col, + const char * text, size_t size) +{ + return mailmime_base64_write_driver(do_write, f, col, text, size); +} + +int mailmime_data_write_mem(MMAPString * f, int * col, + struct mailmime_data * data, + int istext) +{ + return mailmime_data_write_driver(do_write, f, col, data, istext); +} + Added: freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_mem.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/mime/mailmime_write_mem.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,80 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailmime_write_mem.h,v 1.3 2006/06/07 12:52:45 smarinier Exp $ + */ + +#ifndef MAILMIME_WRITE_MEM_H + +#define MAILMIME_WRITE_MEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailmime_types.h> +#include <libetpan/mmapstring.h> + +LIBETPAN_EXPORT +int mailmime_fields_write_mem(MMAPString * f, int * col, + struct mailmime_fields * fields); + +LIBETPAN_EXPORT +int mailmime_content_write_mem(MMAPString * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_content_type_write_mem(MMAPString * f, int * col, + struct mailmime_content * content); + +LIBETPAN_EXPORT +int mailmime_write_mem(MMAPString * f, int * col, + struct mailmime * build_info); + +LIBETPAN_EXPORT +int mailmime_quoted_printable_write_mem(MMAPString * f, int * col, int istext, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_base64_write_mem(MMAPString * f, int * col, + const char * text, size_t size); + +LIBETPAN_EXPORT +int mailmime_data_write_mem(MMAPString * f, int * col, + struct mailmime_data * data, + int istext); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/nntp/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/nntp/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/low-level/nntp/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/nntp/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,8 @@ +top_builddir = ../../.. + +TARGET = libnntp +SOURCES = newsnntp.c newsnntp_socket.c newsnntp_ssl.c +HEADERS = newsnntp.h newsnntp_socket.h newsnntp_ssl.h newsnntp_types.h +INCLUDES = -I$(srcdir)/data-types + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,2495 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp.c,v 1.24 2006/06/26 11:50:27 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "newsnntp.h" + + +#include <stdio.h> +#ifndef _MSC_VER +# include <unistd.h> +# include <netinet/in.h> +# include <netdb.h> +#endif + +#include <string.h> +#include <stdlib.h> +#include <time.h> + +#include "connect.h" +#include "mail.h" +#include "clist.h" + +/* + NNTP Protocol + + RFC 977 + RFC 2980 + + TODO : + + XPAT header range|<message-id> pat [pat...] + + + */ + + + + +#define NNTP_STRING_SIZE 513 + + + +static char * read_line(newsnntp * f); +static char * read_multiline(newsnntp * f, size_t size, + MMAPString * multiline_buffer); +static int parse_response(newsnntp * f, char * response); + +static int send_command(newsnntp * f, char * command); + +newsnntp * newsnntp_new(size_t progr_rate, progress_function * progr_fun) +{ + newsnntp * f; + + f = malloc(sizeof(* f)); + if (f == NULL) + goto err; + + f->nntp_stream = NULL; + f->nntp_readonly = FALSE; + + f->nntp_progr_rate = progr_rate; + f->nntp_progr_fun = progr_fun; + + f->nntp_stream_buffer = mmap_string_new(""); + if (f->nntp_stream_buffer == NULL) + goto free_f; + + f->nntp_response_buffer = mmap_string_new(""); + if (f->nntp_response_buffer == NULL) + goto free_stream_buffer; + + return f; + + free_stream_buffer: + mmap_string_free(f->nntp_stream_buffer); + free_f: + free(f); + err: + return NULL; +} + +void newsnntp_free(newsnntp * f) +{ + if (f->nntp_stream) + newsnntp_quit(f); + + mmap_string_free(f->nntp_response_buffer); + mmap_string_free(f->nntp_stream_buffer); + + free(f); +} + + + + + + + + + + + + + + + + +int newsnntp_quit(newsnntp * f) +{ + char command[NNTP_STRING_SIZE]; + char * response; + int r; + int res; + + if (f->nntp_stream == NULL) + return NEWSNNTP_ERROR_BAD_STATE; + + snprintf(command, NNTP_STRING_SIZE, "QUIT\r\n"); + r = send_command(f, command); + if (r == -1) { + res = NEWSNNTP_ERROR_STREAM; + goto close; + } + + response = read_line(f); + if (response == NULL) { + res = NEWSNNTP_ERROR_STREAM; + goto close; + } + + parse_response(f, response); + + res = NEWSNNTP_NO_ERROR; + + close: + + mailstream_close(f->nntp_stream); + + f->nntp_stream = NULL; + + return res; +} + +int newsnntp_connect(newsnntp * f, mailstream * s) +{ + char * response; + int r; + + if (f->nntp_stream != NULL) + return NEWSNNTP_ERROR_BAD_STATE; + + f->nntp_stream = s; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 200: + f->nntp_readonly = FALSE; + return NEWSNNTP_NO_ERROR; + + case 201: + f->nntp_readonly = TRUE; + return NEWSNNTP_NO_ERROR; + + default: + f->nntp_stream = NULL; + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + + + + + + + + + + + + + + + + + + + +/* +static struct newsnntp_xover_resp_item * get_xover_info(newsnntp * f, + guint32 article); +*/ + +static void newsnntp_multiline_response_free(char * str) +{ + mmap_string_unref(str); +} + +void newsnntp_head_free(char * str) +{ + newsnntp_multiline_response_free(str); +} + +void newsnntp_article_free(char * str) +{ + newsnntp_multiline_response_free(str); +} + +void newsnntp_body_free(char * str) +{ + newsnntp_multiline_response_free(str); +} + +/* ******************** HEADER ******************************** */ + +/* + message content in (* result) is still there until the + next retrieve or top operation on the mailpop3 structure +*/ + +static int newsnntp_get_content(newsnntp * f, char ** result, + size_t * result_len) +{ + int r; + char * response; + MMAPString * buffer; + char * result_multiline; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 220: + case 221: + case 222: + case 223: + buffer = mmap_string_new(""); + if (buffer == NULL) + return NEWSNNTP_ERROR_MEMORY; + + result_multiline = read_multiline(f, 0, buffer); + if (result_multiline == NULL) { + mmap_string_free(buffer); + return NEWSNNTP_ERROR_MEMORY; + } + else { + r = mmap_string_ref(buffer); + if (r < 0) { + mmap_string_free(buffer); + return NEWSNNTP_ERROR_MEMORY; + } + + * result = result_multiline; + * result_len = buffer->len; + return NEWSNNTP_NO_ERROR; + } + + case 412: + return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; + + case 420: + return NEWSNNTP_ERROR_NO_ARTICLE_SELECTED; + + case 423: + return NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER; + + case 430: + return NEWSNNTP_ERROR_ARTICLE_NOT_FOUND; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +int newsnntp_head(newsnntp * f, uint32_t index, char ** result, + size_t * result_len) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "HEAD %i\r\n", index); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_get_content(f, result, result_len); +} + +/* ******************** ARTICLE ******************************** */ + +int newsnntp_article(newsnntp * f, uint32_t index, char ** result, + size_t * result_len) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "ARTICLE %i\r\n", index); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_get_content(f, result, result_len); +} + +/* ******************** BODY ******************************** */ + +int newsnntp_body(newsnntp * f, uint32_t index, char ** result, + size_t * result_len) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "BODY %i\r\n", index); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_get_content(f, result, result_len); +} + +/* ******************** GROUP ******************************** */ + +static struct newsnntp_group_info * +group_info_init(char * name, uint32_t first, uint32_t last, uint32_t count, + char type) +{ + struct newsnntp_group_info * n; + + n = malloc(sizeof(* n)); + + if (n == NULL) + return NULL; + + n->grp_name = strdup(name); + if (n->grp_name == NULL) { + free(n); + return NULL; + } + + n->grp_first = first; + n->grp_last = last; + n->grp_count = count; + n->grp_type = type; + + return n; +} + +static void group_info_free(struct newsnntp_group_info * n) +{ + if (n->grp_name) + free(n->grp_name); + free(n); +} + +static void group_info_list_free(clist * l) +{ + clist_foreach(l, (clist_func) group_info_free, NULL); + clist_free(l); +} + +static int parse_group_info(char * response, + struct newsnntp_group_info ** info); + +int newsnntp_group(newsnntp * f, const char * groupname, + struct newsnntp_group_info ** info) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "GROUP %s\r\n", groupname); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 211: + if (!parse_group_info(f->nntp_response, info)) + return NEWSNNTP_ERROR_INVALID_RESPONSE; + return NEWSNNTP_NO_ERROR; + + case 411: + return NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_group_free(struct newsnntp_group_info * info) +{ + group_info_free(info); +} + +/* ******************** LIST ******************************** */ + +static clist * read_groups_list(newsnntp * f); + +int newsnntp_list(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_groups_list(f); + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_free(clist * l) +{ + group_info_list_free(l); +} + +/* ******************** POST ******************************** */ + +static void send_data(newsnntp * f, const char * message, uint32_t size) +{ + mailstream_send_data(f->nntp_stream, message, size, + f->nntp_progr_rate, f->nntp_progr_fun); +} + + +int newsnntp_post(newsnntp * f, const char * message, size_t size) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "POST\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 340: + break; + + case 440: + return NEWSNNTP_ERROR_POSTING_NOT_ALLOWED; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } + + send_data(f, message, size); + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 240: + return NEWSNNTP_NO_ERROR; + return 1; + + case 441: + return NEWSNNTP_ERROR_POSTING_FAILED; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + +/* ******************** AUTHINFO ******************************** */ + +int newsnntp_authinfo_username(newsnntp * f, const char * username) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "AUTHINFO USER %s\r\n", username); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 482: + return NEWSNNTP_ERROR_AUTHENTICATION_REJECTED; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 281: + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +int newsnntp_authinfo_password(newsnntp * f, const char * password) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "AUTHINFO PASS %s\r\n", password); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 482: + return NEWSNNTP_ERROR_AUTHENTICATION_REJECTED; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 281: + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +/* ******************** LIST OVERVIEW.FMT ******************************** */ + +static clist * read_headers_list(newsnntp * f); + +static void headers_list_free(clist * l) +{ + clist_foreach(l, (clist_func) free, NULL); + clist_free(l); +} + +int newsnntp_list_overview_fmt(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST OVERVIEW.FMT\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_headers_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_overview_fmt_free(clist * l) +{ + headers_list_free(l); +} + + + + + + +/* ******************** LIST ACTIVE ******************************** */ + +int newsnntp_list_active(newsnntp * f, const char * wildcard, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + if (wildcard != NULL) + snprintf(command, NNTP_STRING_SIZE, "LIST ACTIVE %s\r\n", wildcard); + else + snprintf(command, NNTP_STRING_SIZE, "LIST ACTIVE\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_groups_list(f); + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_active_free(clist * l) +{ + group_info_list_free(l); +} + + + + + + +/* ******************** LIST ACTIVE.TIMES ******************************** */ + +static struct newsnntp_group_time * +group_time_new(char * group_name, time_t date, char * email) +{ + struct newsnntp_group_time * n; + + n = malloc(sizeof(* n)); + + if (n == NULL) + return NULL; + + n->grp_name = strdup(group_name); + if (n->grp_name == NULL) { + free(n); + return NULL; + } + + n->grp_email = strdup(email); + if (n->grp_email == NULL) { + free(n->grp_name); + free(n); + return NULL; + } + + n->grp_date = date; + + return n; +} + +static void group_time_free(struct newsnntp_group_time * n) +{ + if (n->grp_name) + free(n->grp_name); + if (n->grp_email) + free(n->grp_email); + free(n); +} + +static void group_time_list_free(clist * l) +{ + clist_foreach(l, (clist_func) group_time_free, NULL); + clist_free(l); +} + + + + + + + +static clist * read_group_time_list(newsnntp * f); + + +int newsnntp_list_active_times(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST ACTIVE.TIMES\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_group_time_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_active_times_free(clist * l) +{ + group_time_list_free(l); +} + + + + + + + + +/* ********************** LIST DISTRIBUTION ***************************** */ + +static struct newsnntp_distrib_value_meaning * +distrib_value_meaning_new(char * value, char * meaning) +{ + struct newsnntp_distrib_value_meaning * n; + + n = malloc(sizeof(* n)); + + if (n == NULL) + return NULL; + + n->dst_value = strdup(value); + if (n->dst_value == NULL) { + free(n); + return NULL; + } + + n->dst_meaning = strdup(meaning); + if (n->dst_meaning == NULL) { + free(n->dst_value); + free(n); + return NULL; + } + + return n; +} + + +static void +distrib_value_meaning_free(struct newsnntp_distrib_value_meaning * n) +{ + if (n->dst_value) + free(n->dst_value); + if (n->dst_meaning) + free(n->dst_meaning); + free(n); +} + +static void distrib_value_meaning_list_free(clist * l) +{ + clist_foreach(l, (clist_func) distrib_value_meaning_free, NULL); + clist_free(l); +} + +static clist * read_distrib_value_meaning_list(newsnntp * f); + + +int newsnntp_list_distribution(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST DISTRIBUTION\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_distrib_value_meaning_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + +void newsnntp_list_distribution_free(clist * l) +{ + distrib_value_meaning_list_free(l); +} + + + + + + + + + + + +/* ********************** LIST DISTRIB.PATS ***************************** */ + +static struct newsnntp_distrib_default_value * +distrib_default_value_new(uint32_t weight, char * group_pattern, char * value) +{ + struct newsnntp_distrib_default_value * n; + + n = malloc(sizeof(* n)); + if (n == NULL) + return NULL; + + n->dst_group_pattern = strdup(group_pattern); + if (n->dst_group_pattern == NULL) { + free(n); + return NULL; + } + + n->dst_value = strdup(value); + if (n->dst_value == NULL) { + free(n->dst_group_pattern); + free(n); + return NULL; + } + + n->dst_weight = weight; + + return n; +} + +static void +distrib_default_value_free(struct newsnntp_distrib_default_value * n) +{ + if (n->dst_group_pattern) + free(n->dst_group_pattern); + if (n->dst_value) + free(n->dst_value); + free(n); +} + +static void distrib_default_value_list_free(clist * l) +{ + clist_foreach(l, (clist_func) distrib_default_value_free, NULL); + clist_free(l); +} + +static clist * read_distrib_default_value_list(newsnntp * f); + +int newsnntp_list_distrib_pats(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST DISTRIB.PATS\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_distrib_default_value_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_distrib_pats_free(clist * l) +{ + distrib_default_value_list_free(l); +} + + + + + + + + + + + + +/* ********************** LIST NEWSGROUPS ***************************** */ + +static struct newsnntp_group_description * +group_description_new(char * group_name, char * description) +{ + struct newsnntp_group_description * n; + + n = malloc(sizeof(* n)); + if (n == NULL) + return NULL; + + n->grp_name = strdup(group_name); + if (n->grp_name == NULL) { + free(n); + return NULL; + } + + n->grp_description = strdup(description); + if (n->grp_description == NULL) { + free(n->grp_name); + free(n); + return NULL; + } + + return n; +} + +static void group_description_free(struct newsnntp_group_description * n) +{ + if (n->grp_name) + free(n->grp_name); + if (n->grp_description) + free(n->grp_description); + free(n); +} + +static void group_description_list_free(clist * l) +{ + clist_foreach(l, (clist_func) group_description_free, NULL); + clist_free(l); +} + +static clist * read_group_description_list(newsnntp * f); + +int newsnntp_list_newsgroups(newsnntp * f, const char * pattern, + clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + if (pattern) + snprintf(command, NNTP_STRING_SIZE, "LIST NEWSGROUPS %s\r\n", pattern); + else + snprintf(command, NNTP_STRING_SIZE, "LIST NEWSGROUPS\r\n"); + + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_group_description_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_newsgroups_free(clist * l) +{ + group_description_list_free(l); +} + + + + + + + + + + + + +/* ******************** LIST SUBSCRIPTIONS ******************************** */ + +static void subscriptions_list_free(clist * l) +{ + clist_foreach(l, (clist_func) free, NULL); + clist_free(l); +} + +static clist * read_subscriptions_list(newsnntp * f); + +int newsnntp_list_subscriptions(newsnntp * f, clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "LIST SUBSCRIPTIONS\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 215: + * result = read_subscriptions_list(f); + return NEWSNNTP_NO_ERROR; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_list_subscriptions_free(clist * l) +{ + subscriptions_list_free(l); +} + + + + + + + + + + + + +/* ******************** LISTGROUP ******************************** */ + +static void articles_list_free(clist * l) +{ + clist_foreach(l, (clist_func) free, NULL); + clist_free(l); +} + +static clist * read_articles_list(newsnntp * f); + +int newsnntp_listgroup(newsnntp * f, const char * group_name, + clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + if (group_name) + snprintf(command, NNTP_STRING_SIZE, "LISTGROUP %s\r\n", group_name); + else + snprintf(command, NNTP_STRING_SIZE, "LISTGROUP\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 211: + * result = read_articles_list(f); + return NEWSNNTP_NO_ERROR; + + case 412: + return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; + + case 502: + return NEWSNNTP_ERROR_NO_PERMISSION; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +void newsnntp_listgroup_free(clist * l) +{ + articles_list_free(l); +} + + + + + + + +/* ********************** MODE READER ***************************** */ + +int newsnntp_mode_reader(newsnntp * f) +{ + char command[NNTP_STRING_SIZE]; + char * response; + int r; + + snprintf(command, NNTP_STRING_SIZE, "MODE READER\r\n"); + + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 200: + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + +/* ********************** DATE ***************************** */ + +#define strfcpy(a,b,c) {if (c) {strncpy(a,b,c);a[c-1]=0;}} + +int newsnntp_date(newsnntp * f, struct tm * tm) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + char year[5]; + char month[3]; + char day[3]; + char hour[3]; + char minute[3]; + char second[3]; + + snprintf(command, NNTP_STRING_SIZE, "DATE\r\n"); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 111: + strfcpy(year, f->nntp_response, 4); + strfcpy(month, f->nntp_response + 4, 2); + strfcpy(day, f->nntp_response + 6, 2); + strfcpy(hour, f->nntp_response + 8, 2); + strfcpy(minute, f->nntp_response + 10, 2); + strfcpy(second, f->nntp_response + 12, 2); + + tm->tm_year = atoi(year); + tm->tm_mon = atoi(month); + tm->tm_mday = atoi(day); + tm->tm_hour = atoi(hour); + tm->tm_min = atoi(minute); + tm->tm_sec = atoi(second); + + return NEWSNNTP_NO_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + + + + + + + + +/* ********************** XHDR ***************************** */ + +static struct newsnntp_xhdr_resp_item * xhdr_resp_item_new(uint32_t article, + char * value) +{ + struct newsnntp_xhdr_resp_item * n; + + n = malloc(sizeof(* n)); + if (n == NULL) + return NULL; + + n->hdr_value = strdup(value); + if (n->hdr_value == NULL) { + free(n); + return NULL; + } + + n->hdr_article = article; + + return n; +} + +static void xhdr_resp_item_free(struct newsnntp_xhdr_resp_item * n) +{ + if (n->hdr_value) + free(n->hdr_value); + free(n); +} + +static void xhdr_resp_list_free(clist * l) +{ + clist_foreach(l, (clist_func) xhdr_resp_item_free, NULL); + clist_free(l); +} + +static clist * read_xhdr_resp_list(newsnntp * f); + +static int newsnntp_xhdr_resp(newsnntp * f, clist ** result); + +int newsnntp_xhdr_single(newsnntp * f, const char * header, uint32_t article, + clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "XHDR %s %i\r\n", header, article); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_xhdr_resp(f, result); +} + +int newsnntp_xhdr_range(newsnntp * f, const char * header, + uint32_t rangeinf, uint32_t rangesup, + clist ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + + snprintf(command, NNTP_STRING_SIZE, "XHDR %s %i-%i\r\n", header, + rangeinf, rangesup); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_xhdr_resp(f, result); +} + +void newsnntp_xhdr_free(clist * l) +{ + xhdr_resp_list_free(l); +} + +static int newsnntp_xhdr_resp(newsnntp * f, clist ** result) +{ + int r; + char * response; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 221: + * result = read_xhdr_resp_list(f); + return NEWSNNTP_NO_ERROR; + + case 412: + return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; + + case 420: + return NEWSNNTP_ERROR_NO_ARTICLE_SELECTED; + + case 430: + return NEWSNNTP_ERROR_ARTICLE_NOT_FOUND; + + case 502: + return NEWSNNTP_ERROR_NO_PERMISSION; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + + + + + + + + + + + + + +/* ********************** XOVER ***************************** */ + +static struct newsnntp_xover_resp_item * +xover_resp_item_new(uint32_t article, + char * subject, + char * author, + char * date, + char * message_id, + char * references, + size_t size, + uint32_t line_count, + clist * others) +{ + struct newsnntp_xover_resp_item * n; + + n = malloc(sizeof(* n)); + if (n == NULL) + return NULL; + + n->ovr_subject = strdup(subject); + if (n->ovr_subject == NULL) { + free(n); + return NULL; + } + + n->ovr_author = strdup(author); + if (n->ovr_author == NULL) { + free(n->ovr_subject); + free(n); + return NULL; + } + + n->ovr_date = strdup(date); + if (n->ovr_date == NULL) { + free(n->ovr_subject); + free(n->ovr_author); + free(n); + return NULL; + } + + n->ovr_message_id = strdup(message_id); + if (n->ovr_message_id == NULL) { + free(n->ovr_subject); + free(n->ovr_author); + free(n->ovr_date); + free(n); + return NULL; + } + + n->ovr_references = strdup(references); + if (n->ovr_references == NULL) { + free(n->ovr_subject); + free(n->ovr_author); + free(n->ovr_date); + free(n->ovr_message_id); + free(n); + return NULL; + } + + n->ovr_article = article; + n->ovr_size = size; + n->ovr_line_count = line_count; + n->ovr_others = others; + + return n; +} + +void xover_resp_item_free(struct newsnntp_xover_resp_item * n) +{ + if (n->ovr_subject) + free(n->ovr_subject); + if (n->ovr_author) + free(n->ovr_author); + if (n->ovr_date) + free(n->ovr_date); + if (n->ovr_message_id) + free(n->ovr_message_id); + if (n->ovr_references) + free(n->ovr_references); + clist_foreach(n->ovr_others, (clist_func) free, NULL); + clist_free(n->ovr_others); + + free(n); +} + +void newsnntp_xover_resp_list_free(clist * l) +{ + clist_foreach(l, (clist_func) xover_resp_item_free, NULL); + clist_free(l); +} + +static clist * read_xover_resp_list(newsnntp * f); + + +static int newsnntp_xover_resp(newsnntp * f, clist ** result); + +int newsnntp_xover_single(newsnntp * f, uint32_t article, + struct newsnntp_xover_resp_item ** result) +{ + char command[NNTP_STRING_SIZE]; + int r; + clist * list; + clistiter * cur; + struct newsnntp_xover_resp_item * item; + + snprintf(command, NNTP_STRING_SIZE, "XOVER %i\r\n", article); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + r = newsnntp_xover_resp(f, &list); + if (r != NEWSNNTP_NO_ERROR) + return r; + + cur = clist_begin(list); + item = clist_content(cur); + clist_free(list); + + * result = item; + + return r; +} + +int newsnntp_xover_range(newsnntp * f, uint32_t rangeinf, uint32_t rangesup, + clist ** result) +{ + int r; + char command[NNTP_STRING_SIZE]; + + snprintf(command, NNTP_STRING_SIZE, "XOVER %i-%i\r\n", rangeinf, rangesup); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + return newsnntp_xover_resp(f, result); +} + +static int newsnntp_xover_resp(newsnntp * f, clist ** result) +{ + int r; + char * response; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 224: + * result = read_xover_resp_list(f); + return NEWSNNTP_NO_ERROR; + + case 412: + return NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED; + + case 420: + return NEWSNNTP_ERROR_NO_ARTICLE_SELECTED; + + case 502: + return NEWSNNTP_ERROR_NO_PERMISSION; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + + + + + + +/* ********************** AUTHINFO GENERIC ***************************** */ + +int newsnntp_authinfo_generic(newsnntp * f, const char * authentificator, + const char * arguments) +{ + char command[NNTP_STRING_SIZE]; + int r; + char * response; + + snprintf(command, NNTP_STRING_SIZE, "AUTHINFO GENERIC %s %s\r\n", + authentificator, arguments); + r = send_command(f, command); + if (r == -1) + return NEWSNNTP_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return NEWSNNTP_ERROR_STREAM; + + r = parse_response(f, response); + + switch (r) { + case 480: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME; + + case 381: + return NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD; + + case 281: + return NEWSNNTP_NO_ERROR; + + case 500: + return NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD; + + case 501: + return NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED; + + case 502: + return NEWSNNTP_ERROR_NO_PERMISSION; + + case 503: + return NEWSNNTP_ERROR_PROGRAM_ERROR; + + default: + return NEWSNNTP_ERROR_UNEXPECTED_RESPONSE; + } +} + + + + + + + + + + + + + + + + + + + +static int parse_space(char ** line) +{ + char * p; + + p = * line; + + while ((* p == ' ') || (* p == '\t')) + p ++; + + if (p != * line) { + * line = p; + return TRUE; + } + else + return FALSE; +} + +static char * cut_token(char * line) +{ + char * p; + char * p_tab; + char * p_space; + + p = line; + + p_space = strchr(line, ' '); + p_tab = strchr(line, '\t'); + if (p_tab == NULL) + p = p_space; + else if (p_space == NULL) + p = p_tab; + else { + if (p_tab < p_space) + p = p_tab; + else + p = p_space; + } + if (p == NULL) + return NULL; + * p = 0; + p ++; + + return p; +} + +static int parse_response(newsnntp * f, char * response) +{ + int code; + + code = strtol(response, &response, 10); + + if (response == NULL) { + f->nntp_response = NULL; + return code; + } + + parse_space(&response); + + if (mmap_string_assign(f->nntp_response_buffer, response) != NULL) + f->nntp_response = f->nntp_response_buffer->str; + else + f->nntp_response = NULL; + + return code; +} + + +static char * read_line(newsnntp * f) +{ + return mailstream_read_line_remove_eol(f->nntp_stream, f->nntp_stream_buffer); +} + +static char * read_multiline(newsnntp * f, size_t size, + MMAPString * multiline_buffer) +{ + return mailstream_read_multiline(f->nntp_stream, size, + f->nntp_stream_buffer, multiline_buffer, + f->nntp_progr_rate, f->nntp_progr_fun); +} + + + + + + + +static int parse_group_info(char * response, + struct newsnntp_group_info ** result) +{ + char * line; + uint32_t first; + uint32_t last; + uint32_t count; + char * name; + struct newsnntp_group_info * info; + + line = response; + + count = strtoul(line, &line, 10); + if (!parse_space(&line)) + return FALSE; + + first = strtoul(line, &line, 10); + if (!parse_space(&line)) + return FALSE; + + last = strtoul(line, &line, 10); + if (!parse_space(&line)) + return FALSE; + + name = line; + + info = group_info_init(name, first, last, count, FALSE); + if (info == NULL) + return FALSE; + + * result = info; + + return TRUE; +} + + +static clist * read_groups_list(newsnntp * f) +{ + char * line; + char * group_name; + uint32_t first; + uint32_t last; + uint32_t count; + int type; + clist * groups_list; + struct newsnntp_group_info * n; + int r; + + groups_list = clist_new(); + if (groups_list == NULL) + goto err; + + while (1) { + char * p; + + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + p = cut_token(line); + if (p == NULL) + continue; + + group_name = line; + line = p; + + last = strtol(line, &line, 10); + if (!parse_space(&line)) + continue; + + first = strtol(line, &line, 10); + if (!parse_space(&line)) + continue; + + count = last - first + 1; + + type = * line; + + n = group_info_init(group_name, first, last, count, type); + if (n == NULL) + goto free_list; + + r = clist_append(groups_list, n); + if (r < 0) { + group_info_free(n); + goto free_list; + } + } + + return groups_list; + + free_list: + group_info_list_free(groups_list); + err: + return NULL; +} + + +static clist * read_headers_list(newsnntp * f) +{ + char * line; + clist * headers_list; + char * header; + int r; + + headers_list = clist_new(); + if (headers_list == NULL) + goto err; + + while (1) { + line = read_line(f); + + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + header = strdup(line); + if (header == NULL) + goto free_list; + + r = clist_append(headers_list, header); + if (r < 0) { + free(header); + goto free_list; + } + } + + return headers_list; + + free_list: + headers_list_free(headers_list); + err: + return NULL; +} + + + + +static clist * read_group_time_list(newsnntp * f) +{ + char * line; + char * group_name; + time_t date; + char * email; + clist * group_time_list; + struct newsnntp_group_time * n; + int r; + + group_time_list = clist_new(); + if (group_time_list == NULL) + goto err; + + while (1) { + char * p; + char * remaining; + + line = read_line(f); + + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + p = cut_token(line); + if (p == NULL) + continue; + + date = strtoul(p, &remaining, 10); + + p = remaining; + parse_space(&p); + + email = p; + + group_name = line; + + n = group_time_new(group_name, date, email); + if (n == NULL) + goto free_list; + + r = clist_append(group_time_list, n); + if (r < 0) { + group_time_free(n); + goto free_list; + } + } + + return group_time_list; + + free_list: + group_time_list_free(group_time_list); + err: + return NULL; +} + + + + +static clist * read_distrib_value_meaning_list(newsnntp * f) +{ + char * line; + char * value; + char * meaning; + clist * distrib_value_meaning_list; + struct newsnntp_distrib_value_meaning * n; + int r; + + distrib_value_meaning_list = clist_new(); + if (distrib_value_meaning_list == NULL) + goto err; + + while (1) { + char * p; + + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + p = cut_token(line); + if (p == NULL) + continue; + + meaning = p; + + value = line; + + n = distrib_value_meaning_new(value, meaning); + if (n == NULL) + goto free_list; + + r = clist_append(distrib_value_meaning_list, n); + if (r < 0) { + distrib_value_meaning_free(n); + goto free_list; + } + } + + return distrib_value_meaning_list; + + free_list: + distrib_value_meaning_list_free(distrib_value_meaning_list); + err: + return NULL; +} + + + + +static clist * read_distrib_default_value_list(newsnntp * f) +{ + char * line; + uint32_t weight; + char * group_pattern; + char * meaning; + clist * distrib_default_value_list; + struct newsnntp_distrib_default_value * n; + int r; + + distrib_default_value_list = clist_new(); + if (distrib_default_value_list == NULL) + goto err; + + while (1) { + char * p; + char * remaining; + + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + p = line; + + weight = strtoul(p, &remaining, 10); + p = remaining; + parse_space(&p); + + p = cut_token(line); + if (p == NULL) + continue; + + meaning = p; + group_pattern = line; + + n = distrib_default_value_new(weight, group_pattern, meaning); + if (n == NULL) + goto free_list; + + r = clist_append(distrib_default_value_list, n); + if (r < 0) { + distrib_default_value_free(n); + goto free_list; + } + } + + return distrib_default_value_list; + + free_list: + distrib_default_value_list_free(distrib_default_value_list); + err: + return NULL; +} + + + +static clist * read_group_description_list(newsnntp * f) +{ + char * line; + char * group_name; + char * description; + clist * group_description_list; + struct newsnntp_group_description * n; + int r; + + group_description_list = clist_new(); + if (group_description_list == NULL) + goto err; + + while (1) { + char * p; + + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + p = cut_token(line); + if (p == NULL) + continue; + + description = p; + + group_name = line; + + n = group_description_new(group_name, description); + if (n == NULL) + goto free_list; + + r = clist_append(group_description_list, n); + if (r < 0) { + group_description_free(n); + goto free_list; + } + } + + return group_description_list; + + free_list: + group_description_list_free(group_description_list); + err: + return NULL; +} + + + +static clist * read_subscriptions_list(newsnntp * f) +{ + char * line; + clist * subscriptions_list; + char * group_name; + int r; + + subscriptions_list = clist_new(); + if (subscriptions_list == NULL) + goto err; + + while (1) { + line = read_line(f); + + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + group_name = strdup(line); + if (group_name == NULL) + goto free_list; + + r = clist_append(subscriptions_list, group_name); + if (r < 0) { + free(group_name); + goto free_list; + } + } + + return subscriptions_list; + + free_list: + subscriptions_list_free(subscriptions_list); + err: + return NULL; +} + + + +static clist * read_articles_list(newsnntp * f) +{ + char * line; + clist * articles_list; + uint32_t * article_num; + int r; + + articles_list = clist_new(); + if (articles_list == NULL) + goto err; + + while (1) { + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + article_num = malloc(sizeof(* article_num)); + if (article_num == NULL) + goto free_list; + * article_num = atoi(line); + + r = clist_append(articles_list, article_num); + if (r < 0) { + free(article_num); + goto free_list; + } + } + + return articles_list; + + free_list: + articles_list_free(articles_list); + err: + return NULL; +} + +static clist * read_xhdr_resp_list(newsnntp * f) +{ + char * line; + uint32_t article; + char * value; + clist * xhdr_resp_list; + struct newsnntp_xhdr_resp_item * n; + int r; + + xhdr_resp_list = clist_new(); + if (xhdr_resp_list == NULL) + goto err; + + while (1) { + line = read_line(f); + + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + article = strtoul(line, &line, 10); + if (!parse_space(&line)) + continue; + + value = line; + + n = xhdr_resp_item_new(article, value); + if (n == NULL) + goto free_list; + + r = clist_append(xhdr_resp_list, n); + if (r < 0) { + xhdr_resp_item_free(n); + goto free_list; + } + } + + return xhdr_resp_list; + + free_list: + xhdr_resp_list_free(xhdr_resp_list); + err: + return NULL; +} + + +static clist * read_xover_resp_list(newsnntp * f) +{ + char * line; + clist * xover_resp_list; + struct newsnntp_xover_resp_item * n; + clist * values_list; + clistiter * current; + uint32_t article; + char * subject; + char * author; + char * date; + char * message_id; + char * references; + size_t size; + uint32_t line_count; + clist * others; + int r; + + xover_resp_list = clist_new(); + if (xover_resp_list == NULL) + goto err; + + while (1) { + char * p; + + line = read_line(f); + + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + /* parse the data separated with \t */ + + values_list = clist_new(); + if (values_list == NULL) + goto free_list; + + while ((p = strchr(line, '\t')) != NULL) { + * p = 0; + p ++; + + r = clist_append(values_list, line); + if (r < 0) + goto free_values_list; + line = p; + } + + r = clist_append(values_list, line); + if (r < 0) + goto free_values_list; + + /* set the known data */ + current = clist_begin(values_list); + article = atoi((char *) clist_content(current)); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + subject = clist_content(current); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + author = clist_content(current); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + date = clist_content(current); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + message_id = clist_content(current); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + references = clist_content(current); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + size = atoi((char *) clist_content(current)); + + current = clist_next(current); + if (current == NULL) { + clist_free(values_list); + continue; + } + line_count = atoi((char *) clist_content(current)); + + current = clist_next(current); + + /* make a copy of the other data */ + others = clist_new(); + if (others == NULL) { + goto free_values_list; + } + + while (current) { + char * val; + char * original_val; + + original_val = clist_content(current); + val = strdup(original_val); + if (val == NULL) { + clist_foreach(others, (clist_func) free, NULL); + clist_free(others); + goto free_list; + } + + r = clist_append(others, val); + if (r < 0) { + goto free_list; + } + + current = clist_next(current); + } + + clist_free(values_list); + + n = xover_resp_item_new(article, subject, author, date, message_id, + references, size, line_count, others); + if (n == NULL) { + clist_foreach(others, (clist_func) free, NULL); + clist_free(others); + goto free_list; + } + + r = clist_append(xover_resp_list, n); + if (r < 0) { + xover_resp_item_free(n); + goto free_list; + } + } + + return xover_resp_list; + + free_list: + newsnntp_xover_resp_list_free(xover_resp_list); + err: + return NULL; + + free_values_list: + clist_foreach(values_list, (clist_func) free, NULL); + clist_free(values_list); + return NULL; +} + +static int send_command(newsnntp * f, char * command) +{ + ssize_t r; + + r = mailstream_write(f->nntp_stream, command, strlen(command)); + if (r == -1) + return -1; + + r = mailstream_flush(f->nntp_stream); + if (r == -1) + return -1; + + return 0; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,189 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp.h,v 1.19 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef NEWSNNTP_H + +#define NEWSNNTP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#include <sys/types.h> +#include <time.h> + +#include <libetpan/clist.h> +#include <libetpan/mailstream.h> +#include <libetpan/newsnntp_socket.h> +#include <libetpan/newsnntp_ssl.h> +#include <libetpan/newsnntp_types.h> + + +newsnntp * newsnntp_new(size_t nntp_progr_rate, + progress_function * nntp_progr_fun); +void newsnntp_free(newsnntp * f); + +int newsnntp_quit(newsnntp * f); +int newsnntp_connect(newsnntp * f, mailstream * s); + +int newsnntp_head(newsnntp * f, uint32_t index, char ** result, + size_t * result_len); +int newsnntp_article(newsnntp * f, uint32_t index, char ** result, + size_t * result_len); +int newsnntp_body(newsnntp * f, uint32_t index, char ** result, + size_t * result_len); + +void newsnntp_head_free(char * str); +void newsnntp_article_free(char * str); +void newsnntp_body_free(char * str); + +int newsnntp_mode_reader(newsnntp * f); + +int newsnntp_date(newsnntp * f, struct tm * tm); + +int newsnntp_authinfo_generic(newsnntp * f, const char * authentificator, + const char * arguments); + +int newsnntp_authinfo_username(newsnntp * f, const char * username); +int newsnntp_authinfo_password(newsnntp * f, const char * password); + +int newsnntp_post(newsnntp * f, const char * message, size_t size); + + + + + + +/******************* requests ******************************/ + +int newsnntp_group(newsnntp * f, const char * groupname, + struct newsnntp_group_info ** info); +void newsnntp_group_free(struct newsnntp_group_info * info); + +/* + elements are struct newsnntp_group_info * + */ + +int newsnntp_list(newsnntp * f, clist ** result); +void newsnntp_list_free(clist * l); + +/* + elements are char * +*/ + +int newsnntp_list_overview_fmt(newsnntp * f, clist ** result); +void newsnntp_list_overview_fmt_free(clist * l); + +/* + elements are struct newsnntp_group_info * +*/ + +int newsnntp_list_active(newsnntp * f, const char * wildcard, clist ** result); +void newsnntp_list_active_free(clist * l); + +/* + elements are struct newsnntp_group_time * +*/ + +int newsnntp_list_active_times(newsnntp * f, clist ** result); +void newsnntp_list_active_times_free(clist * l); + +/* + elements are struct newsnntp_distrib_value_meaning * +*/ + +int newsnntp_list_distribution(newsnntp * f, clist ** result); +void newsnntp_list_distribution_free(clist * l); + +/* + elements are struct newsnntp_distrib_default_value * +*/ + +int newsnntp_list_distrib_pats(newsnntp * f, clist ** result); +void newsnntp_list_distrib_pats_free(clist * l); + +/* + elements are struct newsnntp_group_description * +*/ + +int newsnntp_list_newsgroups(newsnntp * f, const char * pattern, + clist ** result); +void newsnntp_list_newsgroups_free(clist * l); + +/* + elements are char * +*/ + +int newsnntp_list_subscriptions(newsnntp * f, clist ** result); +void newsnntp_list_subscriptions_free(clist * l); + +/* + elements are uint32_t * +*/ + +int newsnntp_listgroup(newsnntp * f, const char * group_name, + clist ** result); +void newsnntp_listgroup_free(clist * l); + +/* + elements are struct newsnntp_xhdr_resp_item * +*/ + +int newsnntp_xhdr_single(newsnntp * f, const char * header, uint32_t article, + clist ** result); +int newsnntp_xhdr_range(newsnntp * f, const char * header, + uint32_t rangeinf, uint32_t rangesup, + clist ** result); +void newsnntp_xhdr_free(clist * l); + +/* + elements are struct newsnntp_xover_resp_item * +*/ + +int newsnntp_xover_single(newsnntp * f, uint32_t article, + struct newsnntp_xover_resp_item ** result); +int newsnntp_xover_range(newsnntp * f, uint32_t rangeinf, uint32_t rangesup, + clist ** result); +void xover_resp_item_free(struct newsnntp_xover_resp_item * n); +void newsnntp_xover_resp_list_free(clist * l); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp_socket.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp_socket.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,81 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp_socket.c,v 1.14 2006/06/26 11:50:28 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "newsnntp_socket.h" + +#include "newsnntp.h" + +#include "connect.h" + +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#define DEFAULT_NNTP_PORT 119 +#define SERVICE_NAME_NNTP "nntp" +#define SERVICE_TYPE_TCP "tcp" + +int newsnntp_socket_connect(newsnntp * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_NNTP, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_NNTP_PORT; + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return NEWSNNTP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_socket_open(s); + if (stream == NULL) { + close(s); + return NEWSNNTP_ERROR_MEMORY; + } + + return newsnntp_connect(f, stream); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp_socket.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp_socket.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,57 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp_socket.h,v 1.14 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef NEWSNNTP_SOCKET_H + +#define NEWSNNTP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif + +#include <libetpan/newsnntp_types.h> + +int newsnntp_socket_connect(newsnntp * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp_ssl.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp_ssl.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,80 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp_ssl.c,v 1.15 2006/06/26 11:50:28 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "newsnntp_ssl.h" + +#include "newsnntp.h" + +#include "connect.h" +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#define DEFAULT_NNTPS_PORT 563 +#define SERVICE_NAME_NNTPS "nntps" +#define SERVICE_TYPE_TCP "tcp" + +int newsnntp_ssl_connect(newsnntp * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_NNTPS, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_NNTPS_PORT; + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return NEWSNNTP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_ssl_open(s); + if (stream == NULL) { + close(s); + return NEWSNNTP_ERROR_CONNECTION_REFUSED; + } + + return newsnntp_connect(f, stream); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp_ssl.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp_ssl.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,57 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp_ssl.h,v 1.15 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef NEWSNNTP_SSL_H + +#define NEWSNNTP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/types.h> +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif + +#include <libetpan/newsnntp_types.h> + +int newsnntp_ssl_connect(newsnntp * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/nntp/newsnntp_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,144 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: newsnntp_types.h,v 1.14 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef NEWSNNTP_TYPES_H + +#define NEWSNNTP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/libetpan-config.h> +#include <libetpan/clist.h> + +#include <libetpan/mailstream.h> +#include <libetpan/mmapstring.h> + +enum { + NEWSNNTP_NO_ERROR = 0, + NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME, + NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_PASSWORD, + NEWSNNTP_ERROR_STREAM, + NEWSNNTP_ERROR_UNEXPECTED, + NEWSNNTP_ERROR_NO_NEWSGROUP_SELECTED, + NEWSNNTP_ERROR_NO_ARTICLE_SELECTED, + NEWSNNTP_ERROR_INVALID_ARTICLE_NUMBER, + NEWSNNTP_ERROR_ARTICLE_NOT_FOUND, + NEWSNNTP_ERROR_UNEXPECTED_RESPONSE, + NEWSNNTP_ERROR_INVALID_RESPONSE, + NEWSNNTP_ERROR_NO_SUCH_NEWS_GROUP, + NEWSNNTP_ERROR_POSTING_NOT_ALLOWED, + NEWSNNTP_ERROR_POSTING_FAILED, + NEWSNNTP_ERROR_PROGRAM_ERROR, + NEWSNNTP_ERROR_NO_PERMISSION, + NEWSNNTP_ERROR_COMMAND_NOT_UNDERSTOOD, + NEWSNNTP_ERROR_COMMAND_NOT_SUPPORTED, + NEWSNNTP_ERROR_CONNECTION_REFUSED, + NEWSNNTP_ERROR_MEMORY, + NEWSNNTP_ERROR_AUTHENTICATION_REJECTED, + NEWSNNTP_ERROR_BAD_STATE +}; + +struct newsnntp +{ + mailstream * nntp_stream; + + int nntp_readonly; + + uint32_t nntp_progr_rate; + progress_function * nntp_progr_fun; + + MMAPString * nntp_stream_buffer; + MMAPString * nntp_response_buffer; + + char * nntp_response; +}; + +typedef struct newsnntp newsnntp; + +struct newsnntp_group_info +{ + char * grp_name; + uint32_t grp_first; + uint32_t grp_last; + uint32_t grp_count; + char grp_type; +}; + +struct newsnntp_group_time { + char * grp_name; + uint32_t grp_date; + char * grp_email; +}; + +struct newsnntp_distrib_value_meaning { + char * dst_value; + char * dst_meaning; +}; + +struct newsnntp_distrib_default_value { + uint32_t dst_weight; + char * dst_group_pattern; + char * dst_value; +}; + +struct newsnntp_group_description { + char * grp_name; + char * grp_description; +}; + +struct newsnntp_xhdr_resp_item { + uint32_t hdr_article; + char * hdr_value; +}; + +struct newsnntp_xover_resp_item { + uint32_t ovr_article; + char * ovr_subject; + char * ovr_author; + char * ovr_date; + char * ovr_message_id; + char * ovr_references; + size_t ovr_size; + uint32_t ovr_line_count; + clist * ovr_others; +}; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/pop3/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/pop3/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/low-level/pop3/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/pop3/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,9 @@ +top_builddir = ../../.. + +TARGET = libpop3 +HEADERS = mailpop3.h mailpop3_socket.h mailpop3_helper.h mailpop3_ssl.h \ + mailpop3_types.h +SOURCES = mailpop3.c mailpop3_helper.c mailpop3_socket.c mailpop3_ssl.c +INCLUDES = -I$(srcdir)/data-types + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1535 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3.c,v 1.28 2006/08/29 23:14:02 hoa Exp $ + */ + +/* + POP3 Protocol + + RFC 1734 + RFC 1939 + RFC 2449 + + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailpop3.h" +#include <stdio.h> +#include <string.h> +#include "md5.h" +#include "mail.h" +#include <stdlib.h> + +#ifdef USE_SASL +#include <sasl/sasl.h> +#include <sasl/saslutil.h> +#endif + +#include "mailsasl.h" + + + + +enum { + POP3_STATE_DISCONNECTED, + POP3_STATE_AUTHORIZATION, + POP3_STATE_TRANSACTION +}; + + + +/* + mailpop3_msg_info structure +*/ + +static struct mailpop3_msg_info * +mailpop3_msg_info_new(unsigned int index, uint32_t size, char * uidl) +{ + struct mailpop3_msg_info * msg; + + msg = malloc(sizeof(* msg)); + if (msg == NULL) + return NULL; + msg->msg_index = index; + msg->msg_size = size; + msg->msg_deleted = FALSE; + msg->msg_uidl = uidl; + + return msg; +} + +static void mailpop3_msg_info_free(struct mailpop3_msg_info * msg) +{ + if (msg->msg_uidl != NULL) + free(msg->msg_uidl); + free(msg); +} + +static void mailpop3_msg_info_tab_free(carray * msg_tab) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * msg; + + msg = carray_get(msg_tab, i); + mailpop3_msg_info_free(msg); + } + carray_free(msg_tab); +} + +static void mailpop3_msg_info_tab_reset(carray * msg_tab) +{ + unsigned int i; + + for(i = 0 ; i < carray_count(msg_tab) ; i++) { + struct mailpop3_msg_info * msg; + msg = carray_get(msg_tab, i); + msg->msg_deleted = FALSE; + } +} + +static inline struct mailpop3_msg_info * +mailpop3_msg_info_tab_find_msg(carray * msg_tab, unsigned int index) +{ + struct mailpop3_msg_info * msg; + + if (index == 0) + return NULL; + + if (index > carray_count(msg_tab)) + return NULL; + + msg = carray_get(msg_tab, index - 1); + + return msg; +} + + + +int mailpop3_get_msg_info(mailpop3 * f, unsigned int index, + struct mailpop3_msg_info ** result) +{ + carray * tab; + struct mailpop3_msg_info * info; + + mailpop3_list(f, &tab); + + if (tab == NULL) + return MAILPOP3_ERROR_BAD_STATE; + + info = mailpop3_msg_info_tab_find_msg(tab, index); + if (info == NULL) + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + + * result = info; + + return MAILPOP3_NO_ERROR; +} + + +/* + mailpop3_capa +*/ + +struct mailpop3_capa * mailpop3_capa_new(char * name, clist * param) +{ + struct mailpop3_capa * capa; + + capa = malloc(sizeof(* capa)); + if (capa == NULL) + return NULL; + capa->cap_name = name; + capa->cap_param = param; + + return capa; +} + + +void mailpop3_capa_free(struct mailpop3_capa * capa) +{ + clist_foreach(capa->cap_param, (clist_func) free, NULL); + clist_free(capa->cap_param); + free(capa->cap_name); + free(capa); +} + +/* + mailpop3 structure +*/ + +mailpop3 * mailpop3_new(size_t progr_rate, progress_function * progr_fun) +{ + mailpop3 * f; + + f = malloc(sizeof(* f)); + if (f == NULL) + goto err; + + f->pop3_timestamp = NULL; + f->pop3_response = NULL; + + f->pop3_stream = NULL; + + f->pop3_progr_rate = progr_rate; + f->pop3_progr_fun = progr_fun; + + f->pop3_stream_buffer = mmap_string_new(""); + if (f->pop3_stream_buffer == NULL) + goto free_f; + + f->pop3_response_buffer = mmap_string_new(""); + if (f->pop3_response_buffer == NULL) + goto free_stream_buffer; + + f->pop3_msg_tab = NULL; + f->pop3_deleted_count = 0; + f->pop3_state = POP3_STATE_DISCONNECTED; + +#ifdef USE_SASL + f->pop3_sasl.sasl_conn = NULL; +#endif + + return f; + + free_stream_buffer: + mmap_string_free(f->pop3_stream_buffer); + free_f: + free(f); + err: + return NULL; +} + + + +void mailpop3_free(mailpop3 * f) +{ +#ifdef USE_SASL + if (f->pop3_sasl.sasl_conn != NULL) { + sasl_dispose((sasl_conn_t **) &f->pop3_sasl.sasl_conn); + mailsasl_unref(); + } +#endif + + if (f->pop3_stream) + mailpop3_quit(f); + + mmap_string_free(f->pop3_response_buffer); + mmap_string_free(f->pop3_stream_buffer); + + free(f); +} + + + + + + + + + + + +/* + operations on mailpop3 structure +*/ + +#define RESPONSE_OK 0 +#define RESPONSE_ERR -1 +#define RESPONSE_AUTH_CONT 1 + +static int send_command(mailpop3 * f, char * command); + +static char * read_line(mailpop3 * f); + +static char * read_multiline(mailpop3 * f, size_t size, + MMAPString * multiline_buffer); + +static int parse_response(mailpop3 * f, char * response); + + +/* get the timestamp in the connection response */ + +#define TIMESTAMP_START '<' +#define TIMESTAMP_END '>' + +static char * mailpop3_get_timestamp(char * response) +{ + char * begin_timestamp; + char * end_timestamp; + char * timestamp; + int len_timestamp; + + if (response == NULL) + return NULL; + + begin_timestamp = strchr(response, TIMESTAMP_START); + + end_timestamp = NULL; + if (begin_timestamp != NULL) { + end_timestamp = strchr(begin_timestamp, TIMESTAMP_END); + if (end_timestamp == NULL) + begin_timestamp = NULL; + } + + if (!begin_timestamp) + return NULL; + + len_timestamp = end_timestamp - begin_timestamp + 1; + + timestamp = malloc(len_timestamp + 1); + if (timestamp == NULL) + return NULL; + strncpy(timestamp, begin_timestamp, len_timestamp); + timestamp[len_timestamp] = '\0'; + + return timestamp; +} + +/* + connect a stream to the mailpop3 structure +*/ + +int mailpop3_connect(mailpop3 * f, mailstream * s) +{ + char * response; + int r; + char * timestamp; + + if (f->pop3_state != POP3_STATE_DISCONNECTED) + return MAILPOP3_ERROR_BAD_STATE; + + f->pop3_stream = s; + + response = read_line(f); + + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_UNAUTHORIZED; + + f->pop3_state = POP3_STATE_AUTHORIZATION; + + timestamp = mailpop3_get_timestamp(f->pop3_response); + if (timestamp != NULL) + f->pop3_timestamp = timestamp; + + return MAILPOP3_NO_ERROR; +} + + +/* + disconnect from a pop3 server +*/ + +int mailpop3_quit(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + char * response; + int r; + int res; + + if ((f->pop3_state != POP3_STATE_AUTHORIZATION) + && (f->pop3_state != POP3_STATE_TRANSACTION)) { + res = MAILPOP3_ERROR_BAD_STATE; + goto close; + } + + snprintf(command, POP3_STRING_SIZE, "QUIT\r\n"); + r = send_command(f, command); + if (r == -1) { + res = MAILPOP3_ERROR_STREAM; + goto close; + } + + response = read_line(f); + if (response == NULL) { + res = MAILPOP3_ERROR_STREAM; + goto close; + } + parse_response(f, response); + + res = MAILPOP3_NO_ERROR; + + close: + if (f->pop3_state != POP3_STATE_DISCONNECTED) + mailstream_close(f->pop3_stream); + + if (f->pop3_timestamp != NULL) { + free(f->pop3_timestamp); + f->pop3_timestamp = NULL; + } + + f->pop3_stream = NULL; + if (f->pop3_msg_tab != NULL) { + mailpop3_msg_info_tab_free(f->pop3_msg_tab); + f->pop3_msg_tab = NULL; + } + + f->pop3_state = POP3_STATE_DISCONNECTED; + + return res; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +int mailpop3_apop(mailpop3 * f, + const char * user, const char * password) +{ + char command[POP3_STRING_SIZE]; + MD5_CTX md5context; + unsigned char md5digest[16]; + char md5string[33]; + char * cmd_ptr; + int r; + int i; + char * response; + + if (f->pop3_state != POP3_STATE_AUTHORIZATION) + return MAILPOP3_ERROR_BAD_STATE; + + if (f->pop3_timestamp == NULL) + return MAILPOP3_ERROR_APOP_NOT_SUPPORTED; + + /* calculate md5 sum */ + + MD5Init(&md5context); + MD5Update(&md5context, f->pop3_timestamp, strlen (f->pop3_timestamp)); + MD5Update(&md5context, password, strlen (password)); + MD5Final(md5digest, &md5context); + + cmd_ptr = md5string; + for(i = 0 ; i < 16 ; i++, cmd_ptr += 2) + snprintf(cmd_ptr, 3, "%02x", md5digest[i]); + * cmd_ptr = 0; + + /* send apop command */ + + snprintf(command, POP3_STRING_SIZE, "APOP %s %s\r\n", user, md5string); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_DENIED; + + f->pop3_state = POP3_STATE_TRANSACTION; + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_user(mailpop3 * f, const char * user) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + if (f->pop3_state != POP3_STATE_AUTHORIZATION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send user command */ + + snprintf(command, POP3_STRING_SIZE, "USER %s\r\n", user); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_BAD_USER; + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_pass(mailpop3 * f, const char * password) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + if (f->pop3_state != POP3_STATE_AUTHORIZATION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send password command */ + + snprintf(command, POP3_STRING_SIZE, "PASS %s\r\n", password); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_BAD_PASSWORD; + + f->pop3_state = POP3_STATE_TRANSACTION; + + return MAILPOP3_NO_ERROR; +} + +static int read_list(mailpop3 * f, carray ** result); + + + +static int read_uidl(mailpop3 * f, carray * msg_tab); + + + +static int mailpop3_do_uidl(mailpop3 * f, carray * msg_tab) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send list command */ + + snprintf(command, POP3_STRING_SIZE, "UIDL\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_CANT_LIST; + + r = read_uidl(f, msg_tab); + if (r != MAILPOP3_NO_ERROR) + return r; + + return MAILPOP3_NO_ERROR; +} + + + +static int mailpop3_do_list(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + int r; + carray * msg_tab; + char * response; + + if (f->pop3_msg_tab != NULL) { + mailpop3_msg_info_tab_free(f->pop3_msg_tab); + f->pop3_msg_tab = NULL; + } + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + /* send list command */ + + snprintf(command, POP3_STRING_SIZE, "LIST\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_CANT_LIST; + + r = read_list(f, &msg_tab); + if (r != MAILPOP3_NO_ERROR) + return r; + + f->pop3_msg_tab = msg_tab; + f->pop3_deleted_count = 0; + + mailpop3_do_uidl(f, msg_tab); + + return MAILPOP3_NO_ERROR; +} + + + +static void mailpop3_list_if_needed(mailpop3 * f) +{ + if (f->pop3_msg_tab == NULL) + mailpop3_do_list(f); +} + +/* + mailpop3_list +*/ + +void mailpop3_list(mailpop3 * f, carray ** result) +{ + mailpop3_list_if_needed(f); + * result = f->pop3_msg_tab; +} + +static inline struct mailpop3_msg_info * +find_msg(mailpop3 * f, unsigned int index) +{ + mailpop3_list_if_needed(f); + + if (f->pop3_msg_tab == NULL) + return NULL; + + return mailpop3_msg_info_tab_find_msg(f->pop3_msg_tab, index); +} + + + + + + + + +static void mailpop3_multiline_response_free(char * str) +{ + mmap_string_unref(str); +} + +void mailpop3_top_free(char * str) +{ + mailpop3_multiline_response_free(str); +} + +void mailpop3_retr_free(char * str) +{ + mailpop3_multiline_response_free(str); +} + +/* + mailpop3_retr + + message content in (* result) is still there until the + next retrieve or top operation on the mailpop3 structure +*/ + +static int +mailpop3_get_content(mailpop3 * f, struct mailpop3_msg_info * msginfo, + char ** result, size_t * result_len) +{ + char * response; + char * result_multiline; + MMAPString * buffer; + int r; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + + buffer = mmap_string_new(""); + if (buffer == NULL) + return MAILPOP3_ERROR_MEMORY; + + result_multiline = read_multiline(f, msginfo->msg_size, buffer); + if (result_multiline == NULL) { + mmap_string_free(buffer); + return MAILPOP3_ERROR_STREAM; + } + else { + r = mmap_string_ref(buffer); + if (r < 0) { + mmap_string_free(buffer); + return MAILPOP3_ERROR_MEMORY; + } + + * result = result_multiline; + * result_len = buffer->len; + return MAILPOP3_NO_ERROR; + } +} + +int mailpop3_retr(mailpop3 * f, unsigned int index, char ** result, + size_t * result_len) +{ + char command[POP3_STRING_SIZE]; + struct mailpop3_msg_info * msginfo; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + msginfo = find_msg(f, index); + + if (msginfo == NULL) { + f->pop3_response = NULL; + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + } + + snprintf(command, POP3_STRING_SIZE, "RETR %i\r\n", index); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + return mailpop3_get_content(f, msginfo, result, result_len); +} + +int mailpop3_top(mailpop3 * f, unsigned int index, + unsigned int count, char ** result, + size_t * result_len) +{ + char command[POP3_STRING_SIZE]; + struct mailpop3_msg_info * msginfo; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + msginfo = find_msg(f, index); + + if (msginfo == NULL) { + f->pop3_response = NULL; + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + } + + snprintf(command, POP3_STRING_SIZE, "TOP %i %i\r\n", index, count); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + return mailpop3_get_content(f, msginfo, result, result_len); +} + +int mailpop3_dele(mailpop3 * f, unsigned int index) +{ + char command[POP3_STRING_SIZE]; + struct mailpop3_msg_info * msginfo; + char * response; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + msginfo = find_msg(f, index); + + if (msginfo == NULL) { + f->pop3_response = NULL; + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + } + + snprintf(command, POP3_STRING_SIZE, "DELE %i\r\n", index); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_NO_SUCH_MESSAGE; + + msginfo->msg_deleted = TRUE; + f->pop3_deleted_count ++; + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_noop(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + char * response; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + snprintf(command, POP3_STRING_SIZE, "NOOP\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + parse_response(f, response); + + return MAILPOP3_NO_ERROR; +} + +int mailpop3_rset(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + char * response; + int r; + + if (f->pop3_state != POP3_STATE_TRANSACTION) + return MAILPOP3_ERROR_BAD_STATE; + + snprintf(command, POP3_STRING_SIZE, "RSET\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + parse_response(f, response); + + if (f->pop3_msg_tab != NULL) { + mailpop3_msg_info_tab_reset(f->pop3_msg_tab); + f->pop3_deleted_count = 0; + } + + return MAILPOP3_NO_ERROR; +} + + + +static int read_capa_resp(mailpop3 * f, clist ** result); + +int mailpop3_capa(mailpop3 * f, clist ** result) +{ + clist * capa_list; + char command[POP3_STRING_SIZE]; + int r; + char * response; + + snprintf(command, POP3_STRING_SIZE, "CAPA\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_CAPA_NOT_SUPPORTED; + + capa_list = NULL; + r = read_capa_resp(f, &capa_list); + if (r != MAILPOP3_NO_ERROR) + return r; + + * result = capa_list; + + return MAILPOP3_NO_ERROR; +} + +void mailpop3_capa_resp_free(clist * capa_list) +{ + clist_foreach(capa_list, (clist_func) mailpop3_capa_free, NULL); + clist_free(capa_list); +} + +int mailpop3_stls(mailpop3 * f) +{ + char command[POP3_STRING_SIZE]; + int r; + char * response; + + snprintf(command, POP3_STRING_SIZE, "STLS\r\n"); + r = send_command(f, command); + if (r == -1) + return MAILPOP3_ERROR_STREAM; + + response = read_line(f); + if (response == NULL) + return MAILPOP3_ERROR_STREAM; + r = parse_response(f, response); + + if (r != RESPONSE_OK) + return MAILPOP3_ERROR_STLS_NOT_SUPPORTED; + + return MAILPOP3_NO_ERROR; +} + + + + + + + + + + + + + + + + + + + + + + + + +#define RESP_OK_STR "+OK" +#define RESP_ERR_STR "-ERR" +#define RESP_AUTH_CONT_STR "+" + + +static int parse_space(char ** line) +{ + char * p; + + p = * line; + + while ((* p == ' ') || (* p == '\t')) + p ++; + + if (p != * line) { + * line = p; + return TRUE; + } + else + return FALSE; +} + +static char * cut_token(char * line) +{ + char * p; + char * p_tab; + char * p_space; + + p = line; + + p_space = strchr(line, ' '); + p_tab = strchr(line, '\t'); + if (p_tab == NULL) + p = p_space; + else if (p_space == NULL) + p = p_tab; + else { + if (p_tab < p_space) + p = p_tab; + else + p = p_space; + } + if (p == NULL) + return NULL; + * p = 0; + p ++; + + return p; +} + + +static int parse_response(mailpop3 * f, char * response) +{ + char * msg; + + if (response == NULL) { + f->pop3_response = NULL; + return RESPONSE_ERR; + } + + if (strncmp(response, RESP_OK_STR, strlen(RESP_OK_STR)) == 0) { + + if (response[strlen(RESP_OK_STR)] == ' ') + msg = response + strlen(RESP_OK_STR) + 1; + else + msg = response + strlen(RESP_OK_STR); + + if (mmap_string_assign(f->pop3_response_buffer, msg)) + f->pop3_response = f->pop3_response_buffer->str; + else + f->pop3_response = NULL; + + return RESPONSE_OK; + } + else if (strncmp(response, RESP_ERR_STR, strlen(RESP_ERR_STR)) == 0) { + + if (response[strlen(RESP_ERR_STR)] == ' ') + msg = response + strlen(RESP_ERR_STR) + 1; + else + msg = response + strlen(RESP_ERR_STR); + + if (mmap_string_assign(f->pop3_response_buffer, msg)) + f->pop3_response = f->pop3_response_buffer->str; + else + f->pop3_response = NULL; + } + + f->pop3_response = NULL; + return RESPONSE_ERR; +} + + + + + +static int parse_auth(mailpop3 * f, char * response) +{ + char * msg; + + if (response == NULL) { + f->pop3_response = NULL; + return RESPONSE_ERR; + } + + if ((strncmp(response, RESP_AUTH_CONT_STR, strlen(RESP_AUTH_CONT_STR)) == 0) && + (strncmp(response, RESP_OK_STR, strlen(RESP_OK_STR)) != 0)) { + + if (response[strlen(RESP_AUTH_CONT_STR)] == ' ') + msg = response + strlen(RESP_AUTH_CONT_STR) + 1; + else + msg = response + strlen(RESP_AUTH_CONT_STR); + + if (mmap_string_assign(f->pop3_response_buffer, msg)) + f->pop3_response = f->pop3_response_buffer->str; + else + f->pop3_response = NULL; + + return RESPONSE_AUTH_CONT; + } + else { + return parse_response(f, response); + } +} + + +static int read_list(mailpop3 * f, carray ** result) +{ + unsigned int index; + uint32_t size; + carray * msg_tab; + struct mailpop3_msg_info * msg; + char * line; + + msg_tab = carray_new(128); + if (msg_tab == NULL) + goto err; + + while (1) { + line = read_line(f); + if (line == NULL) + goto free_list; + + if (mailstream_is_end_multiline(line)) + break; + + index = strtol(line, &line, 10); + + if (!parse_space(&line)) + continue; + + size = strtol(line, &line, 10); + + msg = mailpop3_msg_info_new(index, size, NULL); + if (msg == NULL) + goto free_list; + + if (carray_count(msg_tab) < index) { + int r; + + r = carray_set_size(msg_tab, index); + if (r == -1) + goto free_list; + } + + carray_set(msg_tab, index - 1, msg); + } + + * result = msg_tab; + + return MAILPOP3_NO_ERROR; + + free_list: + mailpop3_msg_info_tab_free(msg_tab); + err: + return MAILPOP3_ERROR_STREAM; +} + + + +static int read_uidl(mailpop3 * f, carray * msg_tab) +{ + unsigned int index; + struct mailpop3_msg_info * msg; + char * line; + + while (1) { + char * uidl; + + line = read_line(f); + if (line == NULL) + goto err; + + if (mailstream_is_end_multiline(line)) + break; + + index = strtol(line, &line, 10); + + if (!parse_space(&line)) + continue; + + uidl = strdup(line); + if (uidl == NULL) + continue; + + if (index > carray_count(msg_tab)) { + free(uidl); + continue; + } + + msg = carray_get(msg_tab, index - 1); + if (msg == NULL) { + free(uidl); + continue; + } + + msg->msg_uidl = uidl; + } + + return MAILPOP3_NO_ERROR; + + err: + return MAILPOP3_ERROR_STREAM; +} + + + +static int read_capa_resp(mailpop3 * f, clist ** result) +{ + char * line; + int res; + clist * list; + int r; + char * name; + clist * param_list; + + list = clist_new(); + if (list == NULL) { + res = MAILPOP3_NO_ERROR; + goto err; + } + + while (1) { + char * next_token; + char * param; + struct mailpop3_capa * capa; + + line = read_line(f); + if (line == NULL) { + res = MAILPOP3_ERROR_STREAM; + goto free_list; + } + + if (mailstream_is_end_multiline(line)) + break; + + next_token = cut_token(line); + name = strdup(line); + if (name == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_list; + } + + param_list = clist_new(); + if (param_list == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_capa_name; + } + + while (next_token != NULL) { + line = next_token; + next_token = cut_token(line); + param = strdup(line); + if (param == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_param_list; + } + r = clist_append(param_list, param); + if (r < 0) { + free(param); + res = MAILPOP3_ERROR_MEMORY; + goto free_param_list; + } + } + + capa = mailpop3_capa_new(name, param_list); + if (capa == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_param_list; + } + + r = clist_append(list, capa); + if (r < 0) { + mailpop3_capa_free(capa); + res = MAILPOP3_ERROR_MEMORY; + goto free_list; + } + } + + * result = list; + + return MAILPOP3_NO_ERROR; + + free_param_list: + clist_foreach(param_list, (clist_func) free, NULL); + clist_free(param_list); + free_capa_name: + free(name); + free_list: + clist_foreach(list, (clist_func) mailpop3_capa_free, NULL); + clist_free(list); + err: + return res; +} + + + +static char * read_line(mailpop3 * f) +{ + return mailstream_read_line_remove_eol(f->pop3_stream, f->pop3_stream_buffer); +} + +static char * read_multiline(mailpop3 * f, size_t size, + MMAPString * multiline_buffer) +{ + return mailstream_read_multiline(f->pop3_stream, size, + f->pop3_stream_buffer, multiline_buffer, + f->pop3_progr_rate, f->pop3_progr_fun); +} + +static int send_command(mailpop3 * f, char * command) +{ + ssize_t r; + + r = mailstream_write(f->pop3_stream, command, strlen(command)); + if (r == -1) + return -1; + + r = mailstream_flush(f->pop3_stream); + if (r == -1) + return -1; + + return 0; +} + + + +#ifdef USE_SASL +static int sasl_getsimple(void * context, int id, + const char ** result, unsigned * len) +{ + mailpop3 * session; + + session = context; + + switch (id) { + case SASL_CB_USER: + if (result != NULL) + * result = session->pop3_sasl.sasl_login; + if (len != NULL) + * len = strlen(session->pop3_sasl.sasl_login); + return SASL_OK; + + case SASL_CB_AUTHNAME: + if (result != NULL) + * result = session->pop3_sasl.sasl_auth_name; + if (len != NULL) + * len = strlen(session->pop3_sasl.sasl_auth_name); + return SASL_OK; + } + + return SASL_FAIL; +} + +static int sasl_getsecret(sasl_conn_t * conn, void * context, int id, + sasl_secret_t ** psecret) +{ + mailpop3 * session; + + session = context; + + switch (id) { + case SASL_CB_PASS: + if (psecret != NULL) + * psecret = session->pop3_sasl.sasl_secret; + return SASL_OK; + } + + return SASL_FAIL; +} + +static int sasl_getrealm(void * context, int id, + const char ** availrealms, + const char ** result) +{ + mailpop3 * session; + + session = context; + + switch (id) { + case SASL_CB_GETREALM: + if (result != NULL) + * result = session->pop3_sasl.sasl_realm; + return SASL_OK; + } + + return SASL_FAIL; +} +#endif + +int mailpop3_auth(mailpop3 * f, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ +#ifdef USE_SASL + int r; + char command[POP3_STRING_SIZE]; + sasl_callback_t sasl_callback[5]; + const char * sasl_out; + unsigned sasl_out_len; + const char * mechusing; + sasl_secret_t * secret; + int res; + size_t len; + char * encoded; + unsigned int encoded_len; + unsigned int max_encoded; + + sasl_callback[0].id = SASL_CB_GETREALM; + sasl_callback[0].proc = sasl_getrealm; + sasl_callback[0].context = f; + sasl_callback[1].id = SASL_CB_USER; + sasl_callback[1].proc = sasl_getsimple; + sasl_callback[1].context = f; + sasl_callback[2].id = SASL_CB_AUTHNAME; + sasl_callback[2].proc = sasl_getsimple; + sasl_callback[2].context = f; + sasl_callback[3].id = SASL_CB_PASS; + sasl_callback[3].proc = sasl_getsecret; + sasl_callback[3].context = f; + sasl_callback[4].id = SASL_CB_LIST_END; + sasl_callback[4].proc = NULL; + sasl_callback[4].context = NULL; + + len = strlen(password); + secret = malloc(sizeof(* secret) + len); + if (secret == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto err; + } + secret->len = len; + memcpy(secret->data, password, len + 1); + + f->pop3_sasl.sasl_server_fqdn = server_fqdn; + f->pop3_sasl.sasl_login = login; + f->pop3_sasl.sasl_auth_name = auth_name; + f->pop3_sasl.sasl_password = password; + f->pop3_sasl.sasl_realm = realm; + f->pop3_sasl.sasl_secret = secret; + + /* init SASL */ + if (f->pop3_sasl.sasl_conn != NULL) { + sasl_dispose((sasl_conn_t **) &f->pop3_sasl.sasl_conn); + f->pop3_sasl.sasl_conn = NULL; + } + else { + mailsasl_ref(); + } + + r = sasl_client_new("pop", server_fqdn, + local_ip_port, remote_ip_port, sasl_callback, 0, + (sasl_conn_t **) &f->pop3_sasl.sasl_conn); + if (r != SASL_OK) { + res = MAILPOP3_ERROR_BAD_USER; + goto free_secret; + } + + r = sasl_client_start(f->pop3_sasl.sasl_conn, + auth_type, NULL, &sasl_out, &sasl_out_len, &mechusing); + if ((r != SASL_CONTINUE) && (r != SASL_OK)) { + res = MAILPOP3_ERROR_BAD_USER; + goto free_sasl_conn; + } + + snprintf(command, POP3_STRING_SIZE, "AUTH %s\r\n", auth_type); + + r = send_command(f, command); + if (r == -1) { + res = MAILPOP3_ERROR_STREAM; + goto free_sasl_conn; + } + + while (1) { + char * response; + + response = read_line(f); + + r = parse_auth(f, response); + switch (r) { + case RESPONSE_OK: + res = MAILPOP3_NO_ERROR; + goto free_sasl_conn; + + case RESPONSE_ERR: + res = MAILPOP3_ERROR_BAD_USER; + goto free_sasl_conn; + + case RESPONSE_AUTH_CONT: + { + size_t response_len; + char * decoded; + unsigned int decoded_len; + unsigned int max_decoded; + int got_response; + + got_response = 1; + if (* f->pop3_response == '\0') + got_response = 0; + + if (got_response) { + response_len = strlen(f->pop3_response); + max_decoded = response_len * 3 / 4; + decoded = malloc(max_decoded + 1); + if (decoded == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_decode64(f->pop3_response, response_len, + decoded, max_decoded + 1, &decoded_len); + + if (r != SASL_OK) { + free(decoded); + res = MAILPOP3_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_client_step(f->pop3_sasl.sasl_conn, + decoded, decoded_len, NULL, &sasl_out, &sasl_out_len); + + free(decoded); + + if ((r != SASL_CONTINUE) && (r != SASL_OK)) { + res = MAILPOP3_ERROR_BAD_USER; + goto free_sasl_conn; + } + } + + max_encoded = ((sasl_out_len + 2) / 3) * 4; + encoded = malloc(max_encoded + 1); + if (encoded == NULL) { + res = MAILPOP3_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_encode64(sasl_out, sasl_out_len, + encoded, max_encoded + 1, &encoded_len); + if (r != SASL_OK) { + free(encoded); + res = MAILPOP3_ERROR_MEMORY; + goto free_sasl_conn; + } + + snprintf(command, POP3_STRING_SIZE, "%s\r\n", encoded); + r = send_command(f, command); + + free(encoded); + + if (r == -1) { + res = MAILPOP3_ERROR_STREAM; + goto free_sasl_conn; + } + } + break; + } + } + + res = MAILPOP3_NO_ERROR; + + free_sasl_conn: + sasl_dispose((sasl_conn_t **) &f->pop3_sasl.sasl_conn); + f->pop3_sasl.sasl_conn = NULL; + mailsasl_unref(); + free_secret: + free(f->pop3_sasl.sasl_secret); + f->pop3_sasl.sasl_secret = NULL; + err: + return res; +#else + return MAILPOP3_ERROR_BAD_USER; +#endif +} Added: freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,108 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3.h,v 1.16 2005/07/16 17:55:57 hoa Exp $ + */ + +#ifndef MAILPOP3_H + +#define MAILPOP3_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailpop3_types.h> + +#include <libetpan/mailpop3_helper.h> + +#include <libetpan/mailpop3_socket.h> +#include <libetpan/mailpop3_ssl.h> + +#define POP3_STRING_SIZE 513 + +mailpop3 * mailpop3_new(size_t pop3_progr_rate, + progress_function * pop3_progr_fun); + +void mailpop3_free(mailpop3 * f); + +int mailpop3_connect(mailpop3 * f, mailstream * s); + +int mailpop3_quit(mailpop3 * f); + + +int mailpop3_apop(mailpop3 * f, const char * user, const char * password); + +int mailpop3_user(mailpop3 * f, const char * user); + +int mailpop3_pass(mailpop3 * f, const char * password); + +void mailpop3_list(mailpop3 * f, carray ** result); + +int mailpop3_retr(mailpop3 * f, unsigned int index, char ** result, + size_t * result_len); + +int mailpop3_top(mailpop3 * f, unsigned int index, + unsigned int count, char ** result, + size_t * result_len); + +int mailpop3_dele(mailpop3 * f, unsigned int index); + +int mailpop3_noop(mailpop3 * f); + +int mailpop3_rset(mailpop3 * f); + +void mailpop3_top_free(char * str); + +void mailpop3_retr_free(char * str); + +int mailpop3_get_msg_info(mailpop3 * f, unsigned int index, + struct mailpop3_msg_info ** result); + +int mailpop3_capa(mailpop3 * f, clist ** result); + +void mailpop3_capa_resp_free(clist * capa_list); + +int mailpop3_stls(mailpop3 * f); + +int mailpop3_auth(mailpop3 * f, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_helper.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_helper.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,82 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_helper.c,v 1.10 2006/06/07 15:10:01 smarinier Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailpop3_helper.h" + +#include <string.h> + +int mailpop3_login_apop(mailpop3 * f, + const char * user, + const char * password) +{ + return mailpop3_apop(f, user, password); +} + + +/* + mailpop3_login + + must be used immediately after connect +*/ + +int mailpop3_login(mailpop3 * f, + const char * user, + const char * password) +{ + int r; + + if ((r = mailpop3_user(f, user)) != MAILPOP3_NO_ERROR) + return r; + + if ((r = mailpop3_pass(f, password)) != MAILPOP3_NO_ERROR) + return r; + + return MAILPOP3_NO_ERROR; +} + +void mailpop3_header_free(char * str) +{ + mailpop3_top_free(str); +} + +int mailpop3_header(mailpop3 * f, uint32_t index, char ** result, + size_t * result_len) +{ + return mailpop3_top(f, index, 0, result, result_len); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_helper.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_helper.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,64 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_helper.h,v 1.8 2006/06/07 15:10:01 smarinier Exp $ + */ + +#ifndef MAILPOP3_HELPER_H + +#define MAILPOP3_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailpop3.h" + +int mailpop3_login_apop(mailpop3 * f, + const char * user, + const char * password); + +int mailpop3_login(mailpop3 * f, + const char * user, + const char * password); + +int mailpop3_header(mailpop3 * f, uint32_t index, char ** result, + size_t * result_len); + +void mailpop3_header_free(char * str); + +#ifdef __cplusplus +} +#endif + +#endif + Added: freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_socket.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_socket.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,80 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_socket.c,v 1.13 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailpop3_socket.h" + +#include "mailpop3.h" + +#include "connect.h" +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#define DEFAULT_POP3_PORT 110 +#define SERVICE_NAME_POP3 "pop3" +#define SERVICE_TYPE_TCP "tcp" + +int mailpop3_socket_connect(mailpop3 * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_POP3, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_POP3_PORT; + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return MAILPOP3_ERROR_CONNECTION_REFUSED; + + stream = mailstream_socket_open(s); + if (stream == NULL) { + close(s); + return MAILPOP3_ERROR_MEMORY; + } + + return mailpop3_connect(f, stream); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_socket.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_socket.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_socket.h,v 1.14 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILPOP3_SOCKET_H + +#define MAILPOP3_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif + +#include <libetpan/mailpop3_types.h> + +int mailpop3_socket_connect(mailpop3 * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_ssl.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_ssl.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,80 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_ssl.c,v 1.13 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailpop3_ssl.h" + +#include "mailpop3.h" + +#include "connect.h" +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#define DEFAULT_POP3S_PORT 995 +#define SERVICE_NAME_POP3S "pop3s" +#define SERVICE_TYPE_TCP "tcp" + +int mailpop3_ssl_connect(mailpop3 * f, const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_POP3S, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_POP3S_PORT; + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return MAILPOP3_ERROR_CONNECTION_REFUSED; + + stream = mailstream_ssl_open(s); + if (stream == NULL) { + close(s); + return MAILPOP3_ERROR_CONNECTION_REFUSED; + } + + return mailpop3_connect(f, stream); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_ssl.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_ssl.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,56 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_ssl.h,v 1.15 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILPOP3_SSL_H + +#define MAILPOP3_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif + +#include <libetpan/mailpop3_types.h> + +int mailpop3_ssl_connect(mailpop3 * f, const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/pop3/mailpop3_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,116 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailpop3_types.h,v 1.18 2006/05/22 13:39:42 hoa Exp $ + */ + +#ifndef MAILPOP3_TYPES_H + +#define MAILPOP3_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/libetpan-config.h> +#include <libetpan/mailstream.h> +#include <libetpan/mmapstring.h> +#include <libetpan/carray.h> +#include <libetpan/clist.h> + +enum { + MAILPOP3_NO_ERROR = 0, + MAILPOP3_ERROR_BAD_STATE, + MAILPOP3_ERROR_UNAUTHORIZED, + MAILPOP3_ERROR_STREAM, + MAILPOP3_ERROR_DENIED, + MAILPOP3_ERROR_BAD_USER, + MAILPOP3_ERROR_BAD_PASSWORD, + MAILPOP3_ERROR_CANT_LIST, + MAILPOP3_ERROR_NO_SUCH_MESSAGE, + MAILPOP3_ERROR_MEMORY, + MAILPOP3_ERROR_CONNECTION_REFUSED, + MAILPOP3_ERROR_APOP_NOT_SUPPORTED, + MAILPOP3_ERROR_CAPA_NOT_SUPPORTED, + MAILPOP3_ERROR_STLS_NOT_SUPPORTED +}; + +struct mailpop3 +{ + char * pop3_response; /* response message */ + char * pop3_timestamp; /* connection timestamp */ + + /* internals */ + mailstream * pop3_stream; + size_t pop3_progr_rate; + progress_function * pop3_progr_fun; + + MMAPString * pop3_stream_buffer; /* buffer for lines reading */ + MMAPString * pop3_response_buffer; /* buffer for responses */ + + carray * pop3_msg_tab; /* list of pop3_msg_info structures */ + int pop3_state; /* state */ + + unsigned int pop3_deleted_count; + + struct { + void * sasl_conn; + const char * sasl_server_fqdn; + const char * sasl_login; + const char * sasl_auth_name; + const char * sasl_password; + const char * sasl_realm; + void * sasl_secret; + } pop3_sasl; +}; + +typedef struct mailpop3 mailpop3; + +struct mailpop3_msg_info +{ + unsigned int msg_index; + uint32_t msg_size; + char * msg_uidl; + int msg_deleted; +}; + + +struct mailpop3_capa { + char * cap_name; + clist * cap_param; /* (char *) */ +}; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/smtp/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/smtp/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,3 @@ +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/low-level/smtp/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/smtp/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,9 @@ +top_builddir = ../../.. + +TARGET = libsmtp +HEADERS = mailsmtp.h mailsmtp_helper.h mailsmtp_socket.h mailsmtp_ssl.h \ + mailsmtp_types.h +SOURCES = mailsmtp.c mailsmtp_helper.c mailsmtp_socket.c mailsmtp_ssl.c +INCLUDES = -I$(srcdir)/data-types + +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/low-level/smtp/TODO ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/smtp/TODO Wed Dec 20 15:28:56 2006 @@ -0,0 +1 @@ +- STARTTLS Added: freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,1366 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa, + * All rights reserved. + * + * SMTP AUTH support by Juergen Graf + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp.c,v 1.27 2006/08/29 23:14:02 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailsmtp.h" +#include "connect.h" +#include "base64.h" +#include "mail.h" + +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif +#include <string.h> +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +#include <stdio.h> + +#ifdef USE_SASL +#include <sasl/sasl.h> +#include <sasl/saslutil.h> +#endif + +#include "mailsasl.h" + +/* + RFC 2821 : SMTP + RFC 1891 : SMTP Service Extension for Delivery Status Notifications + + RFC 1428 : Transition of Internet Mail from Just-Send-8 to 8bit-SMTP/MIME + RFC 1652 : SMTP Service Extension for 8bit-MIMEtransport + RFC 1845 : SMTP Service Extension for Checkpoint/Restart + RFC 1846 : SMTP 521 Reply Code + RFC 1870 : SMTP Service Extension for Message Size Declaration + RFC 1985 : SMTP Service Extension for Remote Message Queue Starting + RFC 2034 : SMTP Service Extension for Returning Enhanced Error Codes + RFC 2442 : The Batch SMTP Media Type + RFC 2487 : SMTP Service Extension for Secure SMTP over TLS + RFC 2505 : Anti-Spam Recommendations for SMTP MTAs + RFC 2554 : SMTP Service Extension for Authentication + RFC 2645 : ON-DEMAND MAIL RELAY (ODMR) SMTP with Dynamic IP Addresses + RFC 2852 : Deliver By SMTP Service Extension + RFC 2920 : SMTP Service Extension for Command Pipelining + RFC 3030 : SMTP Service Extensions for Transmission of Large and Binary MIME + Messages +*/ + +#define SMTP_STATUS_CONTINUE 0x1000 + +mailsmtp * mailsmtp_new(size_t progr_rate, + progress_function * progr_fun) +{ + mailsmtp * session; + + session = malloc(sizeof(* session)); + if (session == NULL) + goto err; + + session->stream = NULL; + + session->progr_rate = progr_rate; + session->progr_fun = progr_fun; + + session->response = NULL; + + session->line_buffer = mmap_string_new(""); + if (session->line_buffer == NULL) + goto free_session; + + session->response_buffer = mmap_string_new(""); + if (session->response_buffer == NULL) + goto free_line_buffer; + + session->esmtp = 0; + session->auth = MAILSMTP_AUTH_NOT_CHECKED; + +#ifdef USE_SASL + session->smtp_sasl.sasl_conn = NULL; +#endif + + return session; + + free_line_buffer: + mmap_string_free(session->line_buffer); + free_session: + free(session); + err: + return NULL; +} + +void mailsmtp_free(mailsmtp * session) +{ +#ifdef USE_SASL + if (session->smtp_sasl.sasl_conn != NULL) { + sasl_dispose((sasl_conn_t **) &session->smtp_sasl.sasl_conn); + mailsasl_unref(); + } +#endif + + if (session->stream) + mailsmtp_quit(session); + + mmap_string_free(session->line_buffer); + mmap_string_free(session->response_buffer); + free(session); +} + +static int send_command(mailsmtp * f, char * command); + +static int read_response(mailsmtp * session); + +/* smtp operations */ + +int mailsmtp_connect(mailsmtp * session, mailstream * s) +{ + int code; + + session->stream = s; + + code = read_response(session); + + switch (code) { + case 220: + return MAILSMTP_NO_ERROR; + + case 554: + session->stream = NULL; + mailstream_close(s); + return MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE; + + default: + session->stream = NULL; + mailstream_close(s); + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + + +#define SMTP_STRING_SIZE 513 + +int mailsmtp_quit(mailsmtp * session) +{ + char command[SMTP_STRING_SIZE]; + int r; + int res; + + snprintf(command, SMTP_STRING_SIZE, "QUIT\r\n"); + r = send_command(session, command); + if (r == -1) { + res = MAILSMTP_ERROR_STREAM; + goto close; + } + r = read_response(session); + if (r == 0) { + res = MAILSMTP_ERROR_STREAM; + goto close; + } + + res = MAILSMTP_NO_ERROR; + + close: + mailstream_close(session->stream); + session->stream = NULL; + + return res; +} + + + +#define HOSTNAME_SIZE 256 + +int mailsmtp_helo(mailsmtp * session) +{ + int r; + char hostname[HOSTNAME_SIZE]; + char command[SMTP_STRING_SIZE]; + + r = gethostname(hostname, HOSTNAME_SIZE); + if (r < 0) + return MAILSMTP_ERROR_HOSTNAME; + + snprintf(command, SMTP_STRING_SIZE, "HELO %s\r\n", hostname); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + session->esmtp = 0; + session->auth = MAILSMTP_AUTH_NOT_CHECKED; + return MAILSMTP_NO_ERROR; + + case 504: + return MAILSMTP_ERROR_NOT_IMPLEMENTED; + + case 550: + return MAILSMTP_ERROR_ACTION_NOT_TAKEN; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +int mailsmtp_mail(mailsmtp * session, const char * from) +{ + int r; + char command[SMTP_STRING_SIZE]; + + snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s>\r\n", from); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + return MAILSMTP_NO_ERROR; + + case 552: + return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 452: + return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE; + + case 550: + return MAILSMTP_ERROR_MAILBOX_UNAVAILABLE; + + case 553: + return MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED; + + case 503: + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +int mailsmtp_rcpt(mailsmtp * session, const char * to) +{ + return mailesmtp_rcpt(session, to, 0, NULL); +} + +int mailsmtp_data(mailsmtp * session) +{ + int r; + char command[SMTP_STRING_SIZE]; + + snprintf(command, SMTP_STRING_SIZE, "DATA\r\n"); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 354: + return MAILSMTP_NO_ERROR; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 554: + return MAILSMTP_ERROR_TRANSACTION_FAILED; + + case 503: + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +static int send_data(mailsmtp * session, const char * message, size_t size); + +int mailsmtp_data_message(mailsmtp * session, + const char * message, + size_t size) +{ + int r; + + r = send_data(session, message, size); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + + r = read_response(session); + + switch(r) { + case 250: + return MAILSMTP_NO_ERROR; + + case 552: + return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION; + + case 554: + return MAILSMTP_ERROR_TRANSACTION_FAILED; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 452: + return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +/* esmtp operations */ + + +/** + * called during mailesmtp_ehlo + * checks EHLO answer for server extensions and sets flags + * in session->esmtp + * checks AUTH methods in session->response and sets flags + * in session->auth + */ +#define isdelim(x) ((x) == ' ' || (x) == '\r' || (x) == '\n' || (x) == '\0') + +int mailesmtp_parse_ehlo(mailsmtp * session) +{ + char * response; + + /* restore data */ + session->esmtp = MAILSMTP_ESMTP; + session->auth = MAILSMTP_AUTH_CHECKED; + + response = session->response; + + /* ESMTP supported extensions : + DSN + EXPN + 8BITMIME + SIZE [<n>] + ETRN + STARTTLS + AUTH <mechanisms...> + */ + while (response != NULL) { + if (!strncasecmp(response, "EXPN", 4) && isdelim(response[4])) + session->esmtp |= MAILSMTP_ESMTP_EXPN; + else if (!strncasecmp(response, "ETRN", 4) && isdelim(response[4])) + session->esmtp |= MAILSMTP_ESMTP_ETRN; + else if (!strncasecmp(response, "DSN", 3) && isdelim(response[3])) + session->esmtp |= MAILSMTP_ESMTP_DSN; + else if (!strncasecmp(response, "8BITMIME", 8) && isdelim(response[8])) + session->esmtp |= MAILSMTP_ESMTP_8BITMIME; + else if (!strncasecmp(response, "STARTTLS", 8) && isdelim(response[8])) + session->esmtp |= MAILSMTP_ESMTP_STARTTLS; + else if (!strncasecmp(response, "SIZE", 4) && isdelim(response[4])) { + session->esmtp |= MAILSMTP_ESMTP_SIZE; + /* TODO: grab optionnal max size */ + } else if (!strncasecmp(response, "AUTH ", 5)) { + response += 5; /* remove "AUTH " */ + while (response[0] != '\n' && response[0] != '\0') { + while (response[0] == ' ') response++; + if (strncasecmp(response, "LOGIN", 5) == 0) { + session->auth |= MAILSMTP_AUTH_LOGIN; + response += 5; + } else if (strncasecmp(response, "CRAM-MD5", 8) == 0) { + session->auth |= MAILSMTP_AUTH_CRAM_MD5; + response += 8; + } else if (strncasecmp(response, "PLAIN", 5) == 0) { + session->auth |= MAILSMTP_AUTH_PLAIN; + response += 5; + } else if (strncasecmp(response, "DIGEST-MD5", 10) == 0) { + session->auth |= MAILSMTP_AUTH_DIGEST_MD5; + response += 10; + } else { + /* unknown auth method - jump to next word or eol */ + while (!isdelim(response[0]) || response[0] == '\r') + response++; + } + } + } + response = strpbrk(response, "\n"); + if (response != NULL) + response++; + } + + return MAILSMTP_NO_ERROR; +} + + +int mailesmtp_ehlo(mailsmtp * session) +{ + int r; + char hostname[HOSTNAME_SIZE]; + char command[SMTP_STRING_SIZE]; + + r = gethostname(hostname, HOSTNAME_SIZE); + if (r != 0) + return MAILSMTP_ERROR_HOSTNAME; + + snprintf(command, SMTP_STRING_SIZE, "EHLO %s\r\n", hostname); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + return mailesmtp_parse_ehlo(session); + + case 504: + return MAILSMTP_ERROR_NOT_IMPLEMENTED; + + case 550: + return MAILSMTP_ERROR_ACTION_NOT_TAKEN; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +/* + if return_full is TRUE, the entire message is returned on error + envid can be NULL +*/ + + +int mailesmtp_mail(mailsmtp * session, + const char * from, + int return_full, + const char * envid) +{ + int r; + char command[SMTP_STRING_SIZE]; + char *body = ""; + +#ifdef notyet + /* TODO: figure out a way for the user to explicity enable this or not */ + if (session->esmtp & MAILSMTP_ESMTP_8BITMIME) + body = " BODY=8BITMIME"; +#endif + + if (session->esmtp & MAILSMTP_ESMTP_DSN) { + if (envid) + snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s> RET=%s ENVID=%s%s\r\n", + from, return_full ? "FULL" : "HDRS", envid, body); + else + snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s> RET=%s%s\r\n", + from, return_full ? "FULL" : "HDRS", body); + } else + snprintf(command, SMTP_STRING_SIZE, "MAIL FROM:<%s>%s\r\n", + from, body); + + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + return MAILSMTP_NO_ERROR; + + case 552: + return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 452: + return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE; + + case 550: + return MAILSMTP_ERROR_MAILBOX_UNAVAILABLE; + + case 553: + return MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED; + + case 503: + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +int mailesmtp_rcpt(mailsmtp * session, + const char * to, + int notify, + const char * orcpt) +{ + int r; + char command[SMTP_STRING_SIZE]; + char notify_str[30] = ""; + char notify_info_str[30] = ""; + + if (notify != 0 && session->esmtp & MAILSMTP_ESMTP_DSN) { + if (notify & MAILSMTP_DSN_NOTIFY_SUCCESS) + strcat(notify_info_str, ",SUCCESS"); + if (notify & MAILSMTP_DSN_NOTIFY_FAILURE) + strcat(notify_info_str, ",FAILURE"); + if (notify & MAILSMTP_DSN_NOTIFY_DELAY) + strcat(notify_info_str, ",DELAY"); + + if (notify & MAILSMTP_DSN_NOTIFY_NEVER) + strcpy(notify_info_str, ",NEVER"); + + notify_info_str[0] = '='; + + strcpy(notify_str, " NOTIFY"); + strcat(notify_str, notify_info_str); + } + + if (orcpt && session->esmtp & MAILSMTP_ESMTP_DSN) + snprintf(command, SMTP_STRING_SIZE, "RCPT TO:<%s>%s ORCPT=%s\r\n", + to, notify_str, orcpt); + else + snprintf(command, SMTP_STRING_SIZE, "RCPT TO:<%s>%s\r\n", to, notify_str); + + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 250: + return MAILSMTP_NO_ERROR; + + case 251: /* not local user, will be forwarded */ + return MAILSMTP_NO_ERROR; + + case 550: + case 450: + return MAILSMTP_ERROR_MAILBOX_UNAVAILABLE; + + case 551: + return MAILSMTP_ERROR_USER_NOT_LOCAL; + + case 552: + return MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION; + + case 553: + return MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED; + + case 451: + return MAILSMTP_ERROR_IN_PROCESSING; + + case 452: + return MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE; + + case 503: + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + case 0: + return MAILSMTP_ERROR_STREAM; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +int auth_map_errors(int err) +{ + switch (err) { + case 235: + return MAILSMTP_NO_ERROR; /* AUTH successfull */ + case 334: + return MAILSMTP_NO_ERROR; /* AUTH in progress */ + case 432: + return MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED; + case 454: + return MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE; + case 504: + return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED; + case 530: + return MAILSMTP_ERROR_AUTH_REQUIRED; + case 534: + return MAILSMTP_ERROR_AUTH_TOO_WEAK; + case 535: + return MAILSMTP_ERROR_AUTH_AUTHENTICATION_FAILED; + case 538: + return MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED; + default: + /* opportunistic approach ;) */ + return MAILSMTP_NO_ERROR; + } +} + +static int mailsmtp_auth_login(mailsmtp * session, + const char * user, const char * pass) +{ + int err; + char command[SMTP_STRING_SIZE]; + char * user64, * pass64; + + user64 = NULL; + pass64 = NULL; + + user64 = encode_base64(user, strlen(user)); + if (user64 == NULL) { + err = MAILSMTP_ERROR_MEMORY; + goto err_free; + } + + pass64 = encode_base64(pass, strlen(pass)); + if (pass64 == NULL) { + err = MAILSMTP_ERROR_MEMORY; + goto err_free; + } + + snprintf(command, SMTP_STRING_SIZE, "%s\r\n", user64); + err = send_command(session, command); + if (err == -1) { + err = MAILSMTP_ERROR_STREAM; + goto err_free; + } + err = read_response(session); + err = auth_map_errors(err); + if (err != MAILSMTP_NO_ERROR) + goto err_free; + + snprintf(command, SMTP_STRING_SIZE, "%s\r\n", pass64); + err = send_command(session, command); + if (err == -1) { + err = MAILSMTP_ERROR_STREAM; + goto err_free; + } + err = read_response(session); + err = auth_map_errors(err); + + err_free: + free(user64); + free(pass64); + + return err; +} + +#if 0 +static int mailsmtp_auth_plain(mailsmtp * session, + const char * user, const char * pass) +{ + int err, len; + char command[SMTP_STRING_SIZE]; + char * plain, * plain64; + + len = strlen(user) + strlen(pass) + 3; + plain = (char *) malloc(len); + if (plain == NULL) { + err = MAILSMTP_ERROR_MEMORY; + goto err; + } + + snprintf(plain, len, "%c%s%c%s", '\0', user, '\0', pass); + plain64 = encode_base64(plain, len - 1); + + snprintf(command, SMTP_STRING_SIZE, "%s\r\n", plain64); + err = send_command(session, command); + if (err == -1) { + err = MAILSMTP_ERROR_STREAM; + goto err_free; + } + + err = read_response(session); + err = auth_map_errors(err); + +err_free: + free(plain64); + free(plain); + + err: + return err; +} + +static char * convert_hex(unsigned char *in, int len) +{ + static char hex[] = "0123456789abcdef"; + char * out; + int i; + + out = (char *) malloc(len * 2 + 1); + if (out == NULL) + return NULL; + + for (i = 0; i < len; i++) { + out[i * 2] = hex[in[i] >> 4]; + out[i * 2 + 1] = hex[in[i] & 15]; + } + + out[i*2] = 0; + + return out; +} + +static char * hash_md5(const char * sec_key, const char * data, int len) +{ + char key[65], digest[24]; + char * hash_hex; + + int sec_len, i; + + sec_len = strlen(sec_key); + + if (sec_len < 64) { + memcpy(key, sec_key, sec_len); + for (i = sec_len; i < 64; i++) { + key[i] = 0; + } + } else { + memcpy(key, sec_key, 64); + } + + hmac_md5(data, len, key, 64, digest); + hash_hex = convert_hex((unsigned char *) digest, 16); + + return hash_hex; +} + +static int mailsmtp_auth_cram_md5(mailsmtp * session, + const char * user, const char * pass) +{ + int err; + char command[SMTP_STRING_SIZE]; + char *response, *auth_hex, *auth; + + response = decode_base64(session->response, strlen(session->response)); + if (response == NULL) return MAILSMTP_ERROR_MEMORY; + + auth_hex = hash_md5(pass, response, strlen(response)); + if (auth_hex == NULL) { + err = MAILSMTP_ERROR_MEMORY; + goto err_free_response; + } + + snprintf(command, SMTP_STRING_SIZE, "%s %s", user, auth_hex); + + auth = encode_base64(command, strlen(command)); + if (auth == NULL) { + err = MAILSMTP_ERROR_MEMORY; + goto err_free_auth_hex; + } + + snprintf(command, SMTP_STRING_SIZE, "%s\r\n", auth); + err = send_command(session, command); + if (err == -1) { + err = MAILSMTP_ERROR_STREAM; + goto err_free; + } + + err = read_response(session); + err = auth_map_errors(err); + +err_free: + free(auth); +err_free_auth_hex: + free(auth_hex); +err_free_response: + free(response); + return err; +} +#endif + +int mailsmtp_auth_type(mailsmtp * session, + const char * user, const char * pass, int type) +{ +#if 0 /* deprecated */ + int err; + char command[SMTP_STRING_SIZE]; + + if (session->auth == MAILSMTP_AUTH_NOT_CHECKED) + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + if ( !(session->auth & type) ) return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED; + + switch (type) { + case MAILSMTP_AUTH_LOGIN: + snprintf(command, SMTP_STRING_SIZE, "AUTH LOGIN\r\n"); + break; + case MAILSMTP_AUTH_PLAIN: + snprintf(command, SMTP_STRING_SIZE, "AUTH PLAIN\r\n"); + break; + case MAILSMTP_AUTH_CRAM_MD5: + snprintf(command, SMTP_STRING_SIZE, "AUTH CRAM-MD5\r\n"); + break; + default: + return MAILSMTP_ERROR_NOT_IMPLEMENTED; + } + + err = send_command(session, command); + if (err == -1) return MAILSMTP_ERROR_STREAM; + + err = read_response(session); + err = auth_map_errors(err); + if (err != MAILSMTP_NO_ERROR) return err; + + switch (type) { + case MAILSMTP_AUTH_LOGIN: + return mailsmtp_auth_login(session, user, pass); + case MAILSMTP_AUTH_PLAIN: + return mailsmtp_auth_plain(session, user, pass); + case MAILSMTP_AUTH_CRAM_MD5: + return mailsmtp_auth_cram_md5(session, user, pass); + default: + return MAILSMTP_ERROR_NOT_IMPLEMENTED; + } +#endif + int err; + char command[SMTP_STRING_SIZE]; + char hostname[SMTP_STRING_SIZE]; + + err = gethostname(hostname, sizeof(hostname)); + if (err < 0) { + return MAILSMTP_ERROR_MEMORY; + } + + if (session->auth == MAILSMTP_AUTH_NOT_CHECKED) + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + if ( !(session->auth & type) ) return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED; + + switch (type) { + case MAILSMTP_AUTH_LOGIN: + { + snprintf(command, SMTP_STRING_SIZE, "AUTH LOGIN\r\n"); + err = send_command(session, command); + if (err == -1) return MAILSMTP_ERROR_STREAM; + + err = read_response(session); + err = auth_map_errors(err); + if (err != MAILSMTP_NO_ERROR) return err; + + return mailsmtp_auth_login(session, user, pass); + } + case MAILSMTP_AUTH_PLAIN: + return mailesmtp_auth_sasl(session, "PLAIN", + hostname, NULL, NULL, user, user, pass, NULL); + + case MAILSMTP_AUTH_CRAM_MD5: + return mailesmtp_auth_sasl(session, "CRAM-MD5", + hostname, NULL, NULL, user, user, pass, NULL); + + case MAILSMTP_AUTH_DIGEST_MD5: + return mailesmtp_auth_sasl(session, "DIGEST-MD5", + hostname, NULL, NULL, user, user, pass, NULL); + + default: + return MAILSMTP_ERROR_NOT_IMPLEMENTED; + } + +} + + +int mailsmtp_auth(mailsmtp * session, const char * user, const char * pass) +{ + if (session->auth == MAILSMTP_AUTH_NOT_CHECKED) + return MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND; + + if (session->auth & MAILSMTP_AUTH_DIGEST_MD5) { + return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_DIGEST_MD5); + } else if (session->auth & MAILSMTP_AUTH_CRAM_MD5) { + return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_CRAM_MD5); + } else if (session->auth & MAILSMTP_AUTH_PLAIN) { + return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_PLAIN); + } else if (session->auth & MAILSMTP_AUTH_LOGIN) { + return mailsmtp_auth_type(session, user, pass, MAILSMTP_AUTH_LOGIN); + } else { + return MAILSMTP_ERROR_AUTH_NOT_SUPPORTED; + } +} + +/* TODO: add mailesmtp_etrn, mailssmtp_expn */ + +int mailesmtp_starttls(mailsmtp * session) { + int r; + + if (!(session->esmtp & MAILSMTP_ESMTP_STARTTLS)) + return MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED; + + r = send_command(session, "STARTTLS\r\n"); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + + switch (r) { + case 220: + return MAILSMTP_NO_ERROR; + + case 454: + return MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE; + + default: + return MAILSMTP_ERROR_UNEXPECTED_CODE; + } +} + +static int parse_response(mailsmtp * session, + char * response) +{ + char * message; + int code; + int cont = 0; + + code = strtol(response, &message, 10); + if (* message == ' ') + mmap_string_append(session->response_buffer, message + 1); + else if (* message == '-') { + cont = SMTP_STATUS_CONTINUE; + mmap_string_append(session->response_buffer, message + 1); + } + else + mmap_string_append(session->response_buffer, message); + + return code | cont; +} + +static char * read_line(mailsmtp * session) +{ + return mailstream_read_line_remove_eol(session->stream, + session->line_buffer); +} + +static int read_response(mailsmtp * session) +{ + char * line; + int code; + + mmap_string_assign(session->response_buffer, ""); + + do { + line = read_line(session); + + if (line != NULL) { + code = parse_response(session, line); + mmap_string_append_c(session->response_buffer, '\n'); + } + else + code = 0; + } + while ((code & SMTP_STATUS_CONTINUE) != 0); + + session->response = session->response_buffer->str; + + return code; +} + + + + + +static int send_command(mailsmtp * f, char * command) +{ + ssize_t r; + + r = mailstream_write(f->stream, command, strlen(command)); + if (r == -1) + return -1; + + r = mailstream_flush(f->stream); + if (r == -1) + return -1; + + return 0; +} + +static int send_data(mailsmtp * session, const char * message, size_t size) +{ + if (mailstream_send_data(session->stream, message, size, + session->progr_rate, session->progr_fun) == -1) + return -1; + + if (mailstream_flush(session->stream) == -1) + return -1; + + return 0; +} + + +const char * mailsmtp_strerror(int errnum) +{ + switch (errnum) { + case MAILSMTP_NO_ERROR: + return "No error"; + case MAILSMTP_ERROR_UNEXPECTED_CODE: + return "Unexpected error code"; + case MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE: + return "Service not available"; + case MAILSMTP_ERROR_STREAM: + return "Stream error"; + case MAILSMTP_ERROR_HOSTNAME: + return "gethostname() failed"; + case MAILSMTP_ERROR_NOT_IMPLEMENTED: + return "Not implemented"; + case MAILSMTP_ERROR_ACTION_NOT_TAKEN: + return "Error, action not taken"; + case MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION: + return "Data exceeds storage allocation"; + case MAILSMTP_ERROR_IN_PROCESSING: + return "Error in processing"; + case MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE: + return "Insufficient system storage"; + case MAILSMTP_ERROR_MAILBOX_UNAVAILABLE: + return "Mailbox unavailable"; + case MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED: + return "Mailbox name not allowed"; + case MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND: + return "Bad command sequence"; + case MAILSMTP_ERROR_USER_NOT_LOCAL: + return "User not local"; + case MAILSMTP_ERROR_TRANSACTION_FAILED: + return "Transaction failed"; + case MAILSMTP_ERROR_MEMORY: + return "Memory error"; + case MAILSMTP_ERROR_CONNECTION_REFUSED: + return "Connection refused"; + case MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE: + return "TLS not available on server for temporary reason"; + case MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED: + return "TLS not supported by server"; + default: + return "Unknown error code"; + } +} + + +#ifdef USE_SASL +static int sasl_getsimple(void * context, int id, + const char ** result, unsigned * len) +{ + mailsmtp * session; + + session = context; + + switch (id) { + case SASL_CB_USER: + if (result != NULL) + * result = session->smtp_sasl.sasl_login; + if (len != NULL) + * len = strlen(session->smtp_sasl.sasl_login); + return SASL_OK; + + case SASL_CB_AUTHNAME: + if (result != NULL) + * result = session->smtp_sasl.sasl_auth_name; + if (len != NULL) + * len = strlen(session->smtp_sasl.sasl_auth_name); + return SASL_OK; + } + + return SASL_FAIL; +} + +static int sasl_getsecret(sasl_conn_t * conn, void * context, int id, + sasl_secret_t ** psecret) +{ + mailsmtp * session; + + session = context; + + switch (id) { + case SASL_CB_PASS: + if (psecret != NULL) + * psecret = session->smtp_sasl.sasl_secret; + return SASL_OK; + } + + return SASL_FAIL; +} + +static int sasl_getrealm(void * context, int id, + const char ** availrealms, + const char ** result) +{ + mailsmtp * session; + + session = context; + + switch (id) { + case SASL_CB_GETREALM: + if (result != NULL) + * result = session->smtp_sasl.sasl_realm; + return SASL_OK; + } + + return SASL_FAIL; +} +#endif + +int mailesmtp_auth_sasl(mailsmtp * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm) +{ +#ifdef USE_SASL + int r; + char command[SMTP_STRING_SIZE]; + sasl_callback_t sasl_callback[5]; + const char * sasl_out; + unsigned sasl_out_len; + const char * mechusing; + sasl_secret_t * secret; + int res; + size_t len; + char * encoded; + unsigned int encoded_len; + unsigned int max_encoded; + + sasl_callback[0].id = SASL_CB_GETREALM; + sasl_callback[0].proc = sasl_getrealm; + sasl_callback[0].context = session; + sasl_callback[1].id = SASL_CB_USER; + sasl_callback[1].proc = sasl_getsimple; + sasl_callback[1].context = session; + sasl_callback[2].id = SASL_CB_AUTHNAME; + sasl_callback[2].proc = sasl_getsimple; + sasl_callback[2].context = session; + sasl_callback[3].id = SASL_CB_PASS; + sasl_callback[3].proc = sasl_getsecret; + sasl_callback[3].context = session; + sasl_callback[4].id = SASL_CB_LIST_END; + sasl_callback[4].proc = NULL; + sasl_callback[4].context = NULL; + + len = strlen(password); + secret = malloc(sizeof(* secret) + len); + if (secret == NULL) { + res = MAILSMTP_ERROR_MEMORY; + goto err; + } + secret->len = len; + memcpy(secret->data, password, len + 1); + + session->smtp_sasl.sasl_server_fqdn = server_fqdn; + session->smtp_sasl.sasl_login = login; + session->smtp_sasl.sasl_auth_name = auth_name; + session->smtp_sasl.sasl_password = password; + session->smtp_sasl.sasl_realm = realm; + session->smtp_sasl.sasl_secret = secret; + + /* init SASL */ + if (session->smtp_sasl.sasl_conn != NULL) { + sasl_dispose((sasl_conn_t **) &session->smtp_sasl.sasl_conn); + session->smtp_sasl.sasl_conn = NULL; + } + else { + mailsasl_ref(); + } + + r = sasl_client_new("smtp", server_fqdn, + local_ip_port, remote_ip_port, sasl_callback, 0, + (sasl_conn_t **) &session->smtp_sasl.sasl_conn); + if (r != SASL_OK) { + res = MAILSMTP_ERROR_AUTH_LOGIN; + goto free_secret; + } + + r = sasl_client_start(session->smtp_sasl.sasl_conn, + auth_type, NULL, &sasl_out, &sasl_out_len, &mechusing); + if ((r != SASL_CONTINUE) && (r != SASL_OK)) { + res = MAILSMTP_ERROR_AUTH_LOGIN; + goto free_sasl_conn; + } + + if (sasl_out_len != 0) { + max_encoded = ((sasl_out_len + 2) / 3) * 4; + encoded = malloc(max_encoded + 1); + if (encoded == NULL) { + res = MAILSMTP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_encode64(sasl_out, sasl_out_len, + encoded, max_encoded + 1, &encoded_len); + if (r != SASL_OK) { + free(encoded); + res = MAILSMTP_ERROR_MEMORY; + goto free_sasl_conn; + } + + snprintf(command, SMTP_STRING_SIZE, "AUTH %s %s\r\n", auth_type, encoded); + + free(encoded); + } + else { + snprintf(command, SMTP_STRING_SIZE, "AUTH %s\r\n", auth_type); + } + + r = send_command(session, command); + if (r == -1) { + res = MAILSMTP_ERROR_STREAM; + goto free_sasl_conn; + } + + while (1) { + r = read_response(session); + switch (r) { + case 220: + case 235: + res = MAILSMTP_NO_ERROR; + goto free_sasl_conn; + + case 334: + { + size_t response_len; + char * decoded; + unsigned int decoded_len; + unsigned int max_decoded; + + response_len = strlen(session->response); + max_decoded = response_len * 3 / 4; + decoded = malloc(max_decoded + 1); + if (decoded == NULL) { + res = MAILSMTP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_decode64(session->response, response_len, + decoded, max_decoded + 1, &decoded_len); + + if (r != SASL_OK) { + free(decoded); + res = MAILSMTP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_client_step(session->smtp_sasl.sasl_conn, + decoded, decoded_len, NULL, &sasl_out, &sasl_out_len); + + free(decoded); + + if ((r != SASL_CONTINUE) && (r != SASL_OK)) { + res = MAILSMTP_ERROR_AUTH_LOGIN; + goto free_sasl_conn; + } + + max_encoded = ((sasl_out_len + 2) / 3) * 4; + encoded = malloc(max_encoded + 1); + if (encoded == NULL) { + res = MAILSMTP_ERROR_MEMORY; + goto free_sasl_conn; + } + + r = sasl_encode64(sasl_out, sasl_out_len, + encoded, max_encoded + 1, &encoded_len); + if (r != SASL_OK) { + free(encoded); + res = MAILSMTP_ERROR_MEMORY; + goto free_sasl_conn; + } + + snprintf(command, SMTP_STRING_SIZE, "%s\r\n", encoded); + r = send_command(session, command); + + free(encoded); + + if (r == -1) { + res = MAILSMTP_ERROR_STREAM; + goto free_sasl_conn; + } + } + break; + + default: + res = auth_map_errors(r); + goto free_sasl_conn; + } + } + + res = MAILSMTP_NO_ERROR; + + free_sasl_conn: + sasl_dispose((sasl_conn_t **) &session->smtp_sasl.sasl_conn); + session->smtp_sasl.sasl_conn = NULL; + mailsasl_unref(); + free_secret: + free(session->smtp_sasl.sasl_secret); + session->smtp_sasl.sasl_secret = NULL; + err: + return res; +#else + return MAILSMTP_ERROR_NOT_IMPLEMENTED; +#endif +} + + +int mailsmtp_noop(mailsmtp * session) +{ + char command[SMTP_STRING_SIZE]; + int r; + + snprintf(command, SMTP_STRING_SIZE, "NOOP\r\n"); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + if (r == 0) + return MAILSMTP_ERROR_STREAM; + + return MAILSMTP_NO_ERROR; +} + +int mailsmtp_reset(mailsmtp * session) +{ + char command[SMTP_STRING_SIZE]; + int r; + + snprintf(command, SMTP_STRING_SIZE, "RSET\r\n"); + r = send_command(session, command); + if (r == -1) + return MAILSMTP_ERROR_STREAM; + r = read_response(session); + if (r == 0) + return MAILSMTP_ERROR_STREAM; + + return MAILSMTP_NO_ERROR; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,137 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp.h,v 1.20 2005/12/20 17:56:11 hoa Exp $ + */ + +#ifndef MAILSMTP_H + +#define MAILSMTP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailsmtp_types.h> +#include <libetpan/mailsmtp_helper.h> +#include <libetpan/mailsmtp_socket.h> +#include <libetpan/mailsmtp_ssl.h> + + +LIBETPAN_EXPORT +mailsmtp * mailsmtp_new(size_t progr_rate, + progress_function * progr_fun); + +LIBETPAN_EXPORT +void mailsmtp_free(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_connect(mailsmtp * session, mailstream * s); + +LIBETPAN_EXPORT +int mailsmtp_quit(mailsmtp * session); + + +/* This call is deprecated and mailesmtp_auth_sasl() should be used instead */ +/** + * Tries AUTH with detected method - "better" method first: + * CRAM-MD5 -> PLAIN -> LOGIN + */ +LIBETPAN_EXPORT +int mailsmtp_auth(mailsmtp * session, const char * user, const char * pass); + +/* This call is deprecated and mailesmtp_auth_sasl() should be used instead */ +/** + * tries to autenticate with the server using given auth-type + * returns MAILSMTP_NO_ERROR on success + */ +LIBETPAN_EXPORT +int mailsmtp_auth_type(mailsmtp * session, + const char * user, const char * pass, int type); + +LIBETPAN_EXPORT +int mailsmtp_helo(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_mail(mailsmtp * session, const char * from); + +LIBETPAN_EXPORT +int mailsmtp_rcpt(mailsmtp * session, const char * to); + +LIBETPAN_EXPORT +int mailsmtp_data(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_data_message(mailsmtp * session, + const char * message, + size_t size); + +LIBETPAN_EXPORT +int mailesmtp_ehlo(mailsmtp * session); + +LIBETPAN_EXPORT +int mailesmtp_mail(mailsmtp * session, + const char * from, + int return_full, + const char * envid); + +LIBETPAN_EXPORT +int mailesmtp_rcpt(mailsmtp * session, + const char * to, + int notify, + const char * orcpt); + +LIBETPAN_EXPORT +int mailesmtp_starttls(mailsmtp * session); + +LIBETPAN_EXPORT +const char * mailsmtp_strerror(int errnum); + +LIBETPAN_EXPORT +int mailesmtp_auth_sasl(mailsmtp * session, const char * auth_type, + const char * server_fqdn, + const char * local_ip_port, + const char * remote_ip_port, + const char * login, const char * auth_name, + const char * password, const char * realm); + +LIBETPAN_EXPORT +int mailsmtp_noop(mailsmtp * session); + +LIBETPAN_EXPORT +int mailsmtp_reset(mailsmtp * session); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_helper.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_helper.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,232 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_helper.c,v 1.14 2006/06/26 11:50:28 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailsmtp.h" +#include <string.h> +#include <stdlib.h> +#include "mail.h" + +int mailsmtp_init(mailsmtp * session) +{ + int r; + + r = mailesmtp_ehlo(session); + + if (r == MAILSMTP_NO_ERROR) + return MAILSMTP_NO_ERROR; + + r = mailsmtp_helo(session); + if (r == MAILSMTP_NO_ERROR) + return MAILSMTP_NO_ERROR; + + return r; +} + + + +int mailesmtp_send(mailsmtp * session, + const char * from, + int return_full, + const char * envid, + clist * addresses, + const char * message, size_t size) +{ + int r; + clistiter * l; + + if (!session->esmtp) + return mailsmtp_send(session, from, addresses, message, size); + + r = mailesmtp_mail(session, from, return_full, envid); + if (r != MAILSMTP_NO_ERROR) + return r; + + for(l = clist_begin(addresses) ; l != NULL; l = clist_next(l)) { + struct esmtp_address * addr; + + addr = clist_content(l); + + r = mailesmtp_rcpt(session, addr->address, addr->notify, addr->orcpt); + if (r != MAILSMTP_NO_ERROR) + return r; + } + + r = mailsmtp_data(session); + if (r != MAILSMTP_NO_ERROR) + return r; + + r = mailsmtp_data_message(session, message, size); + if (r != MAILSMTP_NO_ERROR) + return r; + + return MAILSMTP_NO_ERROR; +} + +int mailsmtp_send(mailsmtp * session, + const char * from, + clist * addresses, + const char * message, size_t size) +{ + int r; + clistiter * l; + + r = mailsmtp_mail(session, from); + if (r != MAILSMTP_NO_ERROR) + return r; + + for(l = clist_begin(addresses) ; l != NULL; l = clist_next(l)) { + struct esmtp_address * addr; + + addr = clist_content(l); + + r = mailsmtp_rcpt(session, addr->address); + if (r != MAILSMTP_NO_ERROR) + return r; + } + + r = mailsmtp_data(session); + if (r != MAILSMTP_NO_ERROR) + return r; + + r = mailsmtp_data_message(session, message, size); + if (r != MAILSMTP_NO_ERROR) + return r; + + return MAILSMTP_NO_ERROR; +} + + + + + + + + + + + + + +/* esmtp addresses and smtp addresses */ + +static struct esmtp_address * esmtp_address_new(char * addr, + int notify, char * orcpt) +{ + struct esmtp_address * esmtpa; + + esmtpa = malloc(sizeof(* esmtpa)); + if (esmtpa == NULL) + return NULL; + + esmtpa->address = strdup(addr); + if (esmtpa->address == NULL) { + free(esmtpa); + return NULL; + } + + if (orcpt != NULL) { + esmtpa->orcpt = strdup(orcpt); + if (esmtpa->orcpt == NULL) { + free(esmtpa->address); + free(esmtpa); + return NULL; + } + } + else + esmtpa->orcpt = NULL; + + esmtpa->notify = notify; + + return esmtpa; +} + +static void esmtp_address_free(struct esmtp_address * addr) +{ + if (addr->orcpt) + free(addr->orcpt); + if (addr->address) + free(addr->address); + + free(addr); +} + +clist * esmtp_address_list_new(void) +{ + return clist_new(); +} + +void esmtp_address_list_free(clist * l) +{ + clist_foreach(l, (clist_func) esmtp_address_free, NULL); + clist_free(l); +} + +int esmtp_address_list_add(clist * list, char * address, + int notify, char * orcpt) +{ + struct esmtp_address * esmtpa; + int r; + + esmtpa = esmtp_address_new(address, notify, orcpt); + if (esmtpa == NULL) + return -1; + + r = clist_append(list, esmtpa); + if (r < 0) { + esmtp_address_free(esmtpa); + return -1; + } + + return 0; +} + +clist * smtp_address_list_new(void) +{ + return esmtp_address_list_new(); +} + +int smtp_address_list_add(clist * list, char * address) +{ + return esmtp_address_list_add(list, address, 0, NULL); +} + +void smtp_address_list_free(clist * l) +{ + esmtp_address_list_free(l); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_helper.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_helper.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,74 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_helper.h,v 1.11 2006/05/22 13:39:43 hoa Exp $ + */ + +#ifndef MAILSMTP_HELPER_H + +#define MAILSMTP_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mailsmtp_types.h" +#include "clist.h" + +int mailsmtp_init(mailsmtp * session); + +int mailesmtp_send(mailsmtp * session, + const char * from, + int return_full, + const char * envid, + clist * addresses, + const char * message, size_t size); + +int mailsmtp_send(mailsmtp * session, + const char * from, + clist * addresses, + const char * message, size_t size); + +clist * esmtp_address_list_new(void); +int esmtp_address_list_add(clist * list, char * address, + int notify, char * orcpt); +void esmtp_address_list_free(clist * l); + +clist * smtp_address_list_new(void); +int smtp_address_list_add(clist * list, char * address); +void smtp_address_list_free(clist * l); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_socket.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_socket.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,108 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_socket.c,v 1.16 2006/06/26 11:50:28 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailsmtp_socket.h" + +#include "mailsmtp.h" + +#include "connect.h" + +#include <stdlib.h> +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#define DEFAULT_SMTP_PORT 25 +#define SERVICE_NAME_SMTP "smtp" +#define SERVICE_TYPE_TCP "tcp" + +int mailsmtp_socket_connect(mailsmtp * session, + const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_SMTP, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_SMTP_PORT; + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return MAILSMTP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_socket_open(s); + if (stream == NULL) { + close(s); + return MAILSMTP_ERROR_MEMORY; + } + + return mailsmtp_connect(session, stream); +} + +int mailsmtp_socket_starttls(mailsmtp * session) { + int r; + int fd; + mailstream_low * low; + mailstream_low * new_low; + + r = mailesmtp_starttls(session); + if (r != MAILSMTP_NO_ERROR) + return r; + + low = mailstream_get_low(session->stream); + fd = mailstream_low_get_fd(low); + if (fd == -1) + return MAILSMTP_ERROR_STREAM; + + new_low = mailstream_low_tls_open(fd); + if (new_low == NULL) + return MAILSMTP_ERROR_STREAM; + + mailstream_low_free(low); + mailstream_set_low(session->stream, new_low); + + return MAILSMTP_NO_ERROR; +} Added: freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_socket.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_socket.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,58 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_socket.h,v 1.17 2005/08/22 10:09:45 smarinier Exp $ + */ + +#ifndef MAILSMTP_SOCKET_H + +#define MAILSMTP_SOCKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/libetpan-config.h> +#include <libetpan/mailsmtp_types.h> + +LIBETPAN_EXPORT +int mailsmtp_socket_connect(mailsmtp * session, + const char * server, uint16_t port); + +LIBETPAN_EXPORT +int mailsmtp_socket_starttls(mailsmtp * session); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_ssl.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_ssl.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,83 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_ssl.c,v 1.14 2006/06/26 11:50:28 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailsmtp_socket.h" + +#include "mailsmtp.h" + +#include "connect.h" + +#include <stdlib.h> +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#define DEFAULT_SMTPS_PORT 465 +#define SERVICE_NAME_SMTPS "smtps" +#define SERVICE_TYPE_TCP "tcp" + +int mailsmtp_ssl_connect(mailsmtp * session, + const char * server, uint16_t port) +{ + int s; + mailstream * stream; + + if (port == 0) { + port = mail_get_service_port(SERVICE_NAME_SMTPS, SERVICE_TYPE_TCP); + if (port == 0) + port = DEFAULT_SMTPS_PORT; + } + + /* Connection */ + + s = mail_tcp_connect(server, port); + if (s == -1) + return MAILSMTP_ERROR_CONNECTION_REFUSED; + + stream = mailstream_ssl_open(s); + if (stream == NULL) { + close(s); + return MAILSMTP_ERROR_CONNECTION_REFUSED; + } + + return mailsmtp_connect(session, stream); +} Added: freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_ssl.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_ssl.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,57 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_ssl.h,v 1.14 2006/05/22 13:39:43 hoa Exp $ + */ + +#ifndef MAILSMTP_SSL_H + +#define MAILSMTP_SSL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif + +#include <libetpan/mailsmtp_types.h> + +int mailsmtp_ssl_connect(mailsmtp * session, + const char * server, uint16_t port); + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_types.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/low-level/smtp/mailsmtp_types.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,138 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: mailsmtp_types.h,v 1.16 2006/10/13 14:24:03 alfie Exp $ + */ + +#ifndef MAILSMTP_TYPES_H + +#define MAILSMTP_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/mailstream.h> +#include <libetpan/mmapstring.h> + +enum { + MAILSMTP_NO_ERROR = 0, + MAILSMTP_ERROR_UNEXPECTED_CODE, + MAILSMTP_ERROR_SERVICE_NOT_AVAILABLE, + MAILSMTP_ERROR_STREAM, + MAILSMTP_ERROR_HOSTNAME, + MAILSMTP_ERROR_NOT_IMPLEMENTED, + MAILSMTP_ERROR_ACTION_NOT_TAKEN, + MAILSMTP_ERROR_EXCEED_STORAGE_ALLOCATION, + MAILSMTP_ERROR_IN_PROCESSING, + MAILSMTP_ERROR_INSUFFICIENT_SYSTEM_STORAGE, + MAILSMTP_ERROR_MAILBOX_UNAVAILABLE, + MAILSMTP_ERROR_MAILBOX_NAME_NOT_ALLOWED, + MAILSMTP_ERROR_BAD_SEQUENCE_OF_COMMAND, + MAILSMTP_ERROR_USER_NOT_LOCAL, + MAILSMTP_ERROR_TRANSACTION_FAILED, + MAILSMTP_ERROR_MEMORY, + MAILSMTP_ERROR_AUTH_NOT_SUPPORTED, + MAILSMTP_ERROR_AUTH_LOGIN, + MAILSMTP_ERROR_AUTH_REQUIRED, + MAILSMTP_ERROR_AUTH_TOO_WEAK, + MAILSMTP_ERROR_AUTH_TRANSITION_NEEDED, + MAILSMTP_ERROR_AUTH_TEMPORARY_FAILTURE, + MAILSMTP_ERROR_AUTH_ENCRYPTION_REQUIRED, + MAILSMTP_ERROR_STARTTLS_TEMPORARY_FAILURE, + MAILSMTP_ERROR_STARTTLS_NOT_SUPPORTED, + MAILSMTP_ERROR_CONNECTION_REFUSED, + MAILSMTP_ERROR_AUTH_AUTHENTICATION_FAILED +}; + +enum { + MAILSMTP_AUTH_NOT_CHECKED = 0, + MAILSMTP_AUTH_CHECKED = 1, + MAILSMTP_AUTH_CRAM_MD5 = 2, + MAILSMTP_AUTH_PLAIN = 4, + MAILSMTP_AUTH_LOGIN = 8, + MAILSMTP_AUTH_DIGEST_MD5 = 16 +}; + +enum { + MAILSMTP_ESMTP = 1, + MAILSMTP_ESMTP_EXPN = 2, + MAILSMTP_ESMTP_8BITMIME = 4, + MAILSMTP_ESMTP_SIZE = 8, + MAILSMTP_ESMTP_ETRN = 16, + MAILSMTP_ESMTP_STARTTLS = 32, + MAILSMTP_ESMTP_DSN = 64 +}; + +struct mailsmtp { + mailstream * stream; + + size_t progr_rate; + progress_function * progr_fun; + + char * response; + + MMAPString * line_buffer; + MMAPString * response_buffer; + + int esmtp; /* contains flags MAILSMTP_ESMTP_* */ + int auth; /* contains flags MAILSMTP_AUTH_* */ + + struct { + void * sasl_conn; + const char * sasl_server_fqdn; + const char * sasl_login; + const char * sasl_auth_name; + const char * sasl_password; + const char * sasl_realm; + void * sasl_secret; + } smtp_sasl; +}; + +typedef struct mailsmtp mailsmtp; + +#define MAILSMTP_DSN_NOTIFY_SUCCESS 1 +#define MAILSMTP_DSN_NOTIFY_FAILURE 2 +#define MAILSMTP_DSN_NOTIFY_DELAY 4 +#define MAILSMTP_DSN_NOTIFY_NEVER 8 + +struct esmtp_address { + char * address; + int notify; + char * orcpt; +}; + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/main/.cvsignore ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/main/.cvsignore Wed Dec 20 15:28:56 2006 @@ -0,0 +1,4 @@ +libetpan_version.h +.libs +*.la +*.lo Added: freeswitch/trunk/libs/libetpan/src/main/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/main/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,7 @@ +TARGET = libmain +HEADERS = libetpan.h libetpan_version.h + +SOURCES = libetpan_version.c + +top_builddir = ../.. +include $(top_builddir)/Rules Added: freeswitch/trunk/libs/libetpan/src/main/libetpan.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/main/libetpan.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,123 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: libetpan.h,v 1.16 2006/08/05 02:34:07 hoa Exp $ + */ + +#ifndef LIBETPAN_H + +#define LIBETPAN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <libetpan/libetpan_version.h> +#include <libetpan/maildriver.h> +#include <libetpan/mailmessage.h> +#include <libetpan/mailfolder.h> +#include <libetpan/mailstorage.h> +#include <libetpan/mailthread.h> +#include <libetpan/mailsmtp.h> +#include <libetpan/charconv.h> +#include <libetpan/mailsem.h> +#include <libetpan/carray.h> +#include <libetpan/chash.h> +#include <libetpan/maillock.h> + +/* mbox driver */ +#include <libetpan/mboxdriver.h> +#include <libetpan/mboxdriver_message.h> +#include <libetpan/mboxdriver_cached.h> +#include <libetpan/mboxdriver_cached_message.h> +#include <libetpan/mboxstorage.h> + +/* MH driver */ +#include <libetpan/mhdriver.h> +#include <libetpan/mhdriver_message.h> +#include <libetpan/mhdriver_cached.h> +#include <libetpan/mhdriver_cached_message.h> +#include <libetpan/mhstorage.h> + +/* IMAP4rev1 driver */ +#include <libetpan/imapdriver.h> +#include <libetpan/imapdriver_message.h> +#include <libetpan/imapdriver_cached.h> +#include <libetpan/imapdriver_cached_message.h> +#include <libetpan/imapstorage.h> + +/* POP3 driver */ +#include <libetpan/pop3driver.h> +#include <libetpan/pop3driver_message.h> +#include <libetpan/pop3driver_cached.h> +#include <libetpan/pop3driver_cached_message.h> +#include <libetpan/pop3storage.h> + +/* Hotmail */ +#include <libetpan/hotmailstorage.h> + +/* NNTP driver */ +#include <libetpan/nntpdriver.h> +#include <libetpan/nntpdriver_message.h> +#include <libetpan/nntpdriver_cached.h> +#include <libetpan/nntpdriver_cached_message.h> +#include <libetpan/nntpstorage.h> + +/* maildir driver */ +#include <libetpan/maildirdriver.h> +#include <libetpan/maildirdriver_message.h> +#include <libetpan/maildirdriver_cached.h> +#include <libetpan/maildirdriver_cached_message.h> +#include <libetpan/maildirstorage.h> + +/* db driver */ +#include <libetpan/dbdriver.h> +#include <libetpan/dbdriver_message.h> +#include <libetpan/dbstorage.h> + +/* message which content is given by a MIME structure */ +#include <libetpan/mime_message_driver.h> + +/* message which content given by a string */ +#include <libetpan/data_message_driver.h> + +/* engine */ +#include <libetpan/mailprivacy.h> +#include <libetpan/mailengine.h> +#include <libetpan/mailprivacy_gnupg.h> +#include <libetpan/mailprivacy_smime.h> + +#ifdef __cplusplus +} +#endif + +#endif Added: freeswitch/trunk/libs/libetpan/src/main/libetpan_version.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/main/libetpan_version.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,52 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: libetpan_version.c,v 1.4 2006/05/22 13:39:45 hoa Exp $ + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "libetpan_version.h" + +/* version of libEtPan! at runtime */ + +int libetpan_get_version_major(void) +{ + return LIBETPAN_VERSION_MAJOR; +} + +int libetpan_get_version_minor(void) +{ + return LIBETPAN_VERSION_MINOR; +} Added: freeswitch/trunk/libs/libetpan/src/main/libetpan_version.h.in ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/main/libetpan_version.h.in Wed Dec 20 15:28:56 2006 @@ -0,0 +1,57 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001 - 2003 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id: libetpan_version.h.in,v 1.3 2004/10/17 23:18:03 g_roualland Exp $ + */ + +#ifndef LIBETPAN_VERSION_H + +#define LIBETPAN_VERSION_H + +#ifndef LIBETPAN_VERSION_MAJOR +#define LIBETPAN_VERSION_MAJOR @VERSION_MAJOR@ +#endif + +#ifndef LIBETPAN_VERSION_MINOR +#define LIBETPAN_VERSION_MINOR @VERSION_MINOR@ +#endif + +#ifndef LIBETPAN_REENTRANT +#if @REENTRANT@ +#define LIBETPAN_REENTRANT 1 +#endif +#endif + +int libetpan_get_version_major(void); +int libetpan_get_version_minor(void); + +#endif Added: freeswitch/trunk/libs/libetpan/src/windows/dirent.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/windows/dirent.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,22 @@ +#include <win_etpan.h> + +DIR *opendir (const char *__name) { +#ifdef _DEBUG + fprintf( stderr, "opendir inimplemented\n"); +#endif + return NULL; +} + +int closedir (DIR *__dirp) { +#ifdef _DEBUG + fprintf( stderr, "closedir inimplemented\n"); +#endif + return 0; +} + +struct dirent *readdir (DIR *__dirp) { +#ifdef _DEBUG + fprintf( stderr, "readdir inimplemented\n"); +#endif + return NULL; +} Added: freeswitch/trunk/libs/libetpan/src/windows/misc.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/windows/misc.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,21 @@ +#include <stdio.h> +#include <fcntl.h> +#include <io.h> +#include <sys/types.h> +#include <sys/stat.h> + +int mkstemp (char *tmp_template) { + int fd; + char * res; + +#ifdef _DEBUG + printf("mkstemp:%s\n", tmp_template); +#endif + fd = -1; + res = mktemp( tmp_template); + if (res && *res) { + fd = open( res, _O_BINARY | _O_CREAT | _O_TEMPORARY | _O_EXCL, _S_IREAD | _S_IWRITE); + } + + return fd; +} \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/src/windows/mmap.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/windows/mmap.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,24 @@ +#include "win_etpan.h" + + +void *mmap (void *__addr, size_t __len, int __prot, + int __flags, int __fd, size_t __offset) { +#ifdef _DEBUG + fprintf( stderr, "mmap inimplemented\n"); +#endif + return MAP_FAILED; +} + +int munmap (void *__addr, size_t __len) { +#ifdef _DEBUG + fprintf( stderr, "mmap inimplemented\n"); +#endif + return -1; +} + +int msync (void *__addr, size_t __len, int __flags) { +#ifdef _DEBUG + fprintf( stderr, "mmap inimplemented\n"); +#endif + return -1; +} Added: freeswitch/trunk/libs/libetpan/src/windows/time_r.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/windows/time_r.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,11 @@ +#include <time.h> +#include <win_etpan.h> + +struct tm *gmtime_r (const time_t *timep, struct tm *result) { + *result = *gmtime( timep); + return result; +} +struct tm *localtime_r (const time_t *timep, struct tm *result) { + *result = *localtime( timep); + return result; +} \ No newline at end of file Added: freeswitch/trunk/libs/libetpan/src/windows/win_etpan.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/windows/win_etpan.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,127 @@ +/* MS C++ Compiler includes */ +#ifndef __win_etpan_h +#define __win_etpan_h + +#include <direct.h> +#include <process.h> +#include <stdlib.h> +#include <errno.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* for compatibility */ +#define S_IRUSR _S_IREAD +#define S_IWUSR _S_IWRITE + +/* compatibility is allowed with MULTITHREAD DLL */ +extern struct tm *gmtime_r (const time_t *timep, struct tm *result); +extern struct tm *localtime_r (const time_t *timep, struct tm *result); + +/* stat */ +typedef unsigned short mode_t; +#define S_ISREG(x) ((x & _S_IFMT) == _S_IFREG) +#define S_ISDIR(x) ((x & _S_IFMT) == _S_IFDIR) + +/* same properties ? */ +#define random() rand() + +/* same function */ +#define ftruncate( x, y) chsize( x, y) + +/* create and open */ +extern int mkstemp (char *tmp_template); + +/* why is this missing ? */ +#define sleep(x) _sleep(x) + +#define link(x, y) (errno = EPERM) + +/* ------------------------------------------------- */ +/* dirent */ + +struct dirent + { + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; /* We must not include limits.h! */ + }; + +/* This is the data type of directory stream objects. + The actual structure is opaque to users. */ +typedef struct __dirstream DIR; + +/* Open a directory stream on NAME. + Return a DIR stream on the directory, or NULL if it could not be opened. */ +extern DIR *opendir (const char *__name); + +/* Close the directory stream DIRP. + Return 0 if successful, -1 if not. */ +extern int closedir (DIR *__dirp); + +/* Read a directory entry from DIRP. Return a pointer to a `struct + dirent' describing the entry, or NULL for EOF or error. The + storage returned may be overwritten by a later readdir call on the + same DIR stream.*/ +extern struct dirent *readdir (DIR *__dirp); +/* ------------------------------------------------- */ + +/* ------------------------------------------------- */ +/* sys/mman */ + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ + + +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((void *) -1) + +/* Map addresses starting near ADDR and extending for LEN bytes. from + OFFSET into the file FD describes according to PROT and FLAGS. If ADDR + is nonzero, it is the desired mapping address. If the MAP_FIXED bit is + set in FLAGS, the mapping will be at ADDR exactly (which must be + page-aligned); otherwise the system chooses a convenient nearby address. + The return value is the actual mapping address chosen or MAP_FAILED + for errors (in which case `errno' is set). A successful `mmap' call + deallocates any previous mapping for the affected region. */ +extern void *mmap (void *__addr, size_t __len, int __prot, + int __flags, int __fd, size_t __offset); + +/* Deallocate any mapping for the region starting at ADDR and extending LEN + bytes. Returns 0 if successful, -1 for errors (and sets errno). */ +extern int munmap (void *__addr, size_t __len); + +/* Synchronize the region starting at ADDR and extending LEN bytes with the + file it maps. Filesystem operations on a file being mapped are + unpredictable before this is done. Flags are from the MS_* set. */ +extern int msync (void *__addr, size_t __len, int __flags); + +/* Flags to `msync'. */ +/* Sync memory asynchronously. */ +#if 0 /* unsupported */ +#define MS_ASYNC 1 +#endif +#define MS_SYNC 4 /* Synchronous memory sync. */ +/* Invalidate the caches. */ +#if 0 /* unsupported */ +#define MS_INVALIDATE 2 +#endif + +/* ------------------------------------------------- */ + +#ifdef __cplusplus +} +#endif +#endif /* __win_etpan_h */ Added: freeswitch/trunk/libs/libetpan/src/windows/wsocket.cpp ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/src/windows/wsocket.cpp Wed Dec 20 15:28:56 2006 @@ -0,0 +1,27 @@ +/* + +Special class, supposed to be held as a static object in +any class that uses the sockets api - Socket.cc, GenericSocket.cc, +NetAddress.cc + +*/ +class win_sockets { + public: + win_sockets() { + + int success = WSAStartup((WORD)0x0101, &winsockData); + if (success != 0) + { + throw "Cannot startup windows sockets api."; + } + } + ~win_sockets() { + WSACleanup(); + } + + private: + WSADATA winsockData; +}; + +/* Initialise sockets */ +static win_sockets wsastartup; Added: freeswitch/trunk/libs/libetpan/tests/Makefile ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/Makefile Wed Dec 20 15:28:56 2006 @@ -0,0 +1,43 @@ +SHELL = /bin/sh +RM = rm -fr +CFLAGS = -g -O2 -W -Wall `libetpan-config --cflags` +CC = gcc +PROGS = smime decrypt pgp frm frm-tree frm-simple readmsg readmsg-simple \ + fetch-attachment compose-msg smtpsend readmsg-uid +LDFLAGS = `libetpan-config --libs` +INSTALL = install -c + +prefix=/usr/local +bindir=$(prefix)/bin + +FRMCOMMON=frm-common.o option-parser.o + +all: $(PROGS) + +frm: $(FRMCOMMON) frm.o + +frm-tree: $(FRMCOMMON) frm-tree.o + +frm-simple: $(FRMCOMMON) frm-simple.o + +readmsg: option-parser.o readmsg.o readmsg-common.o + +readmsg-secure: option-parser.o readmsg-secure.o \ + readmsg-common.o + +readmsg-simple: option-parser.o readmsg-simple.o + +readmsg-uid: option-parser.o readmsg-uid.o + +fetch-attachment: option-parser.o fetch-attachment.o \ + readmsg-common.o + +compose-msg: compose-msg.o + +smtpsend: smtpsend.o + +# no install +install: + +clean: + $(RM) *.o $(PROGS) *~ .libs Added: freeswitch/trunk/libs/libetpan/tests/README ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/README Wed Dec 20 15:28:56 2006 @@ -0,0 +1,58 @@ +compose-msg +----------- + +creates a RFC 2822 message with MIME parts + +syntax: compose-msg "text" filename + + + +all the following programs will take as argument : + + --driver=(pop3|imap|nntp|mbox|mh) -d pop3 (pop3|imap|nntp|mbox|mh) + + default driver is mbox + + --server={server-name} -s {server-name} + --port={port-number} -p {port-number} + --tls -t + --starttls -x + --user={login} -u {login} + --password={password} -v {password} + --path={mailbox} -l {mailbox} + --apop -a + --cache={directory} -c {directory} + +the default driver is mbox with the path /var/mail/$USER + +frm-simple, frm, frm-tree +------------------------- + +frm-simple will list all the mails of a mailbox without any MIME decoding. + +frm will list all the mails of a mailbox and will decode the fields. + +frm-tree will do the same thing as frm and will also show the threads + of the folder. + + +fetch-attachment +---------------- + + fetch-attachment gets all the named attachment of the given message +of the chosen mailbox and writes them on the current directory. + + The program should be given message numbers (as given by frm) as +additionnal arguments. + + +readmsg-simple, readmsg +----------------------- + + readmsg-simple will display the content of the given messages. +All the content (headers and body) will be displayed. + + readmsg will display only the text parts of the given messages. + + The program should be given message numbers (as given by frm) as +additionnal arguments. Added: freeswitch/trunk/libs/libetpan/tests/compose-msg.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/compose-msg.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,317 @@ +#include <libetpan/libetpan.h> +#include <string.h> +#include <stdlib.h> + +#define DEST_CHARSET "iso-8859-1" + +/* build a mime parameter */ + +static struct mailmime_parameter * +mailmime_param_new_with_data(char * name, char * value) +{ + char * param_name; + char * param_value; + struct mailmime_parameter * param; + + param_name = strdup(name); + if (param_name == NULL) + goto err; + + param_value = strdup(value); + if (param_value == NULL) + goto free_name; + + param = mailmime_parameter_new(param_name, param_value); + if (param == NULL) + goto free_value; + + return param; + + free_value: + free(param_value); + free_name: + free(param_name); + err: + return NULL; +} + + +/* build sample fields */ + +static struct mailimf_fields * build_fields(void) +{ + struct mailimf_mailbox_list * from; + struct mailimf_address_list * to; + char * subject; + int r; + struct mailimf_fields * new_fields; + + /* subject field */ + + subject = strdup("this is a sample"); + if (subject == NULL) { + goto err; + } + + /* from field */ + + from = mailimf_mailbox_list_new_empty(); + if (from == NULL) { + goto free_subject; + } + + r = mailimf_mailbox_list_add_parse(from, + "DINH Viet Hoa <hoa@sourceforge.net>"); + if (r != MAILIMF_NO_ERROR) { + goto free_from; + } + + /* to field */ + + to = mailimf_address_list_new_empty(); + if (to == NULL) { + goto free_from; + } + + r = mailimf_address_list_add_parse(to, + "Paul <claws@thewildbeast.co.uk>"); + if (r != MAILIMF_NO_ERROR) { + goto free_to; + } + + new_fields = mailimf_fields_new_with_data(from /* from */, + NULL /* sender */, NULL /* reply-to */, + to, NULL /* cc */, NULL /* bcc */, NULL /* in-reply-to */, + NULL /* references */, + subject); + if (new_fields == NULL) + goto free_to; + + return new_fields; + + free_to: + mailimf_address_list_free(to); + free_from: + mailimf_mailbox_list_free(from); + free_subject: + free(subject); + err: + return NULL; +} + + + +/* text is a string, build a mime part containing this string */ + +static struct mailmime * build_body_text(char * text) +{ + struct mailmime_fields * mime_fields; + struct mailmime * mime_sub; + struct mailmime_content * content; + struct mailmime_parameter * param; + int r; + + /* text/plain part */ + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT); + if (mime_fields == NULL) { + goto err; + } + + content = mailmime_content_new_with_str("text/plain"); + if (content == NULL) { + goto free_fields; + } + + param = mailmime_param_new_with_data("charset", DEST_CHARSET); + if (param == NULL) { + goto free_content; + } + + r = clist_append(content->ct_parameters, param); + if (r < 0) { + mailmime_parameter_free(param); + goto free_content; + } + + mime_sub = mailmime_new_empty(content, mime_fields); + if (mime_sub == NULL) { + goto free_content; + } + + r = mailmime_set_body_text(mime_sub, text, strlen(text)); + if (r != MAILIMF_NO_ERROR) { + goto free_mime; + } + + return mime_sub; + + free_mime: + mailmime_free(mime_sub); + goto err; + free_content: + mailmime_content_free(content); + free_fields: + mailmime_fields_free(mime_fields); + err: + return NULL; +} + + +/* build a mime part containing the given file */ + +static struct mailmime * build_body_file(char * filename) +{ + struct mailmime_fields * mime_fields; + struct mailmime * mime_sub; + struct mailmime_content * content; + struct mailmime_parameter * param; + char * dup_filename; + int r; + + /* text/plain part */ + + dup_filename = strdup(filename); + if (dup_filename == NULL) + goto err; + + mime_fields = + mailmime_fields_new_filename(MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + dup_filename, MAILMIME_MECHANISM_BASE64); + if (mime_fields == NULL) + goto free_dup_filename; + + content = mailmime_content_new_with_str("text/plain"); + if (content == NULL) { + goto free_fields; + } + + param = mailmime_param_new_with_data("charset", DEST_CHARSET); + if (param == NULL) { + goto free_content; + } + + r = clist_append(content->ct_parameters, param); + if (r < 0) { + mailmime_parameter_free(param); + goto free_content; + } + + mime_sub = mailmime_new_empty(content, mime_fields); + if (mime_sub == NULL) { + goto free_content; + } + + dup_filename = strdup(filename); + if (dup_filename == NULL) + goto free_mime; + + r = mailmime_set_body_file(mime_sub, dup_filename); + if (r != MAILIMF_NO_ERROR) { + goto free_mime; + } + + return mime_sub; + + free_mime: + mailmime_free(mime_sub); + goto err; + free_content: + mailmime_content_free(content); + free_fields: + mailmime_fields_free(mime_fields); + goto err; + free_dup_filename: + free(dup_filename); + err: + return NULL; +} + + +/* build an empty message */ + +static struct mailmime * build_message(struct mailimf_fields * fields) +{ + struct mailmime * mime; + + /* message */ + + mime = mailmime_new_message_data(NULL); + if (mime == NULL) { + goto err; + } + + mailmime_set_imf_fields(mime, fields); + + return mime; + + err: + return NULL; +} + + +int main(int argc, char ** argv) +{ + struct mailimf_fields * fields; + char * text; + char * filename; + struct mailmime * message; + struct mailmime * text_part; + struct mailmime * file_part; + int r; + int col; + + if (argc < 3) { + printf("syntax: compose-msg \"text\" filename\n"); + return 1; + } + + fields = build_fields(); + if (fields == NULL) + goto err; + + message = build_message(fields); + if (message == NULL) + goto free_fields; + + text = argv[1]; + text_part = build_body_text(text); + if (text_part == NULL) + goto free_message; + + filename = argv[2]; + file_part = build_body_file(filename); + if (file_part == NULL) + goto free_text; + + r = mailmime_smart_add_part(message, text_part); + if (r != MAILIMF_NO_ERROR) + goto free_file; + + r = mailmime_smart_add_part(message, file_part); + if (r != MAILIMF_NO_ERROR) + goto free_file_alone; + + col = 0; + mailmime_write(stdout, &col, message); + + mailmime_free(message); + + return 0; + + free_file_alone: + mailmime_free(file_part); + goto free_text; + free_file: + mailmime_free(file_part); + free_text: + mailmime_free(text_part); + free_message: + mailmime_free(message); + goto err; + free_fields: + mailimf_fields_free(fields); + err: + printf("error memory\n"); + return 1; +} Added: freeswitch/trunk/libs/libetpan/tests/decrypt.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/decrypt.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,162 @@ +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <stdlib.h> +#include <string.h> + +int get_content_of_file(char * filename, char ** p_content, size_t * p_length) +{ + int r; + void * mapped; + struct stat stat_buf; + int fd; + char * content; + + r = stat(filename, &stat_buf); + if (r < 0) + goto err; + + content = malloc(stat_buf.st_size + 1); + if (content == NULL) + goto err; + + fd = open(filename, O_RDONLY); + if (fd < 0) + goto free; + + mapped = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapped == (void *) MAP_FAILED) + goto close; + + memcpy(content, mapped, stat_buf.st_size); + content[stat_buf.st_size] = '\0'; + + munmap(mapped, stat_buf.st_size); + close(fd); + + * p_content = content; + * p_length = stat_buf.st_size; + + return 0; + + close: + close(fd); + free: + free(content); + err: + return -1; +} + +int main(int argc, char ** argv) +{ + char * content; + size_t length; + mailmessage * msg; + int r; + struct mailprivacy * privacy; + struct mailmime * mime; + struct mailmime * encrypted_mime; + int col; + clist * encryption_id_list; + + privacy = mailprivacy_new("/Users/hoa/tmp", 1); + if (privacy == NULL) { + goto err; + } + + r = mailprivacy_gnupg_init(privacy); + if (r != MAIL_NO_ERROR) { + goto free_privacy; + } + + r = mailprivacy_smime_init(privacy); + mailprivacy_smime_set_cert_dir(privacy, + "/Users/hoa/LibEtPan/libetpan/tests/keys/cert"); + mailprivacy_smime_set_CA_dir(privacy, + "/Users/hoa/LibEtPan/libetpan/tests/keys/ca"); + mailprivacy_smime_set_private_keys_dir(privacy, + "/Users/hoa/LibEtPan/libetpan/tests/keys/private"); + + mailprivacy_gnupg_set_encryption_id(privacy, "xxxx@xxxx", "coin"); + mailprivacy_smime_set_encryption_id(privacy, "xxxx@xxxx", "coin"); + + if (argc < 2) { + fprintf(stderr, "syntax: decrypt [message]\n"); + goto done_gpg; + } + + r = get_content_of_file(argv[1], &content, &length); + if (r < 0) { + fprintf(stderr, "file not found %s\n", argv[1]); + goto done_gpg; + } + + msg = data_message_init(content, length); + if (msg == NULL) { + fprintf(stderr, "unexpected error\n"); + goto free_content; + } + + r = mailprivacy_msg_get_bodystructure(privacy, msg, &mime); + if (r != MAIL_NO_ERROR) { + fprintf(stderr, "unexpected error\n"); + goto free_content; + } + + mailmime_write(stdout, &col, mime); + + { + clist * id_list; + unsigned int i; + clistiter * iter; + + id_list = mailprivacy_gnupg_encryption_id_list(privacy, msg); + if (id_list != NULL) { + for(iter = clist_begin(id_list) ; iter != NULL ; iter = clist_next(iter)) { + char * str; + + str = clist_content(iter); + fprintf(stderr, "%s\n", str); + } + } + } + + { + clist * id_list; + unsigned int i; + clistiter * iter; + + id_list = mailprivacy_smime_encryption_id_list(privacy, msg); + if (id_list != NULL) { + for(iter = clist_begin(id_list) ; iter != NULL ; iter = clist_next(iter)) { + char * str; + + str = clist_content(iter); + fprintf(stderr, "%s\n", str); + } + } + } + + mailprivacy_gnupg_encryption_id_list_clear(privacy, msg); + + mailmessage_free(msg); + + free(content); + mailprivacy_smime_done(privacy); + mailprivacy_gnupg_done(privacy); + mailprivacy_free(privacy); + + exit(EXIT_SUCCESS); + + free_content: + free(content); + done_gpg: + mailprivacy_gnupg_done(privacy); + free_privacy: + mailprivacy_free(privacy); + err: + exit(EXIT_FAILURE); +} Added: freeswitch/trunk/libs/libetpan/tests/fetch-attachment.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/fetch-attachment.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,274 @@ +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <libetpan/libetpan.h> + +#include "option-parser.h" +#include "readmsg-common.h" + +/* write content to the given filename */ + +static int etpan_write_data(char * filename, char * data, size_t len) +{ + size_t write_len; + FILE * f; + int res; + mode_t old_umask; + + old_umask = umask(0077); + f = fopen(filename, "w"); + umask(old_umask); + if (f == NULL) { + res = ERROR_FILE; + goto err; + } + + write_len = fwrite(data, 1, len, f); + if (write_len < len) { + res = ERROR_FILE; + goto close; + } + + fclose(f); + + return NO_ERROR; + + close: + fclose(f); + err: + return res; +} + + +/* save attachment */ + +static int save_mime_content(mailmessage * msg_info, + struct mailmime * mime_part) +{ + char * body; + size_t body_len; + int r; + char * filename; + struct mailmime_single_fields fields; + int res; + + memset(&fields, 0, sizeof(struct mailmime_single_fields)); + if (mime_part->mm_mime_fields != NULL) + mailmime_single_fields_init(&fields, mime_part->mm_mime_fields, + mime_part->mm_content_type); + + filename = fields.fld_disposition_filename; + + if (filename == NULL) + filename = fields.fld_content_name; + + if (filename == NULL) + return ERROR_INVAL; + + r = etpan_fetch_message(msg_info, mime_part, &fields, &body, &body_len); + if (r != NO_ERROR) { + res = r; + goto err; + } + + printf("writing %s, %i bytes\n", filename, body_len); + + r = etpan_write_data(filename, body, body_len); + if (r != NO_ERROR) { + res = r; + goto free; + } + + mailmime_decoded_part_free(body); + + return NO_ERROR; + + free: + mailmime_decoded_part_free(body); + err: + return res; +} + + + +/* fetch attachments */ + +static int etpan_fetch_mime(FILE * f, mailmessage * msg_info, + struct mailmime * mime) +{ + int r; + clistiter * cur; + struct mailmime_single_fields fields; + int res; + + memset(&fields, 0, sizeof(struct mailmime_single_fields)); + if (mime->mm_mime_fields != NULL) + mailmime_single_fields_init(&fields, mime->mm_mime_fields, + mime->mm_content_type); + + switch(mime->mm_type) { + case MAILMIME_SINGLE: + save_mime_content(msg_info, mime); + + break; + + case MAILMIME_MULTIPLE: + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + + r = etpan_fetch_mime(f, msg_info, clist_content(cur)); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + break; + + case MAILMIME_MESSAGE: + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + r = etpan_fetch_mime(f, msg_info, mime->mm_data.mm_message.mm_msg_mime); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + break; + } + + return NO_ERROR; + + err: + return res; +} + + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + while (optind < argc) { + mailmessage * msg; + uint32_t msg_num; + struct mailmime * mime; + + msg_num = strtoul(argv[optind], NULL, 10); + + r = mailsession_get_message(folder->fld_session, msg_num, &msg); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found ** - %s\n", msg_num, + maildriver_strerror(r)); + optind ++; + continue; + } + + r = mailmessage_get_bodystructure(msg, &mime); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found - %s **\n", msg_num, + maildriver_strerror(r)); + mailmessage_free(msg); + optind ++; + continue; + } + + r = etpan_fetch_mime(stdout, msg, mime); + + mailmessage_free(msg); + + optind ++; + } + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} Added: freeswitch/trunk/libs/libetpan/tests/frm-common.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/frm-common.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,159 @@ +#include "frm-common.h" + +#include <string.h> +#include <stdlib.h> + +#define DEST_CHARSET "iso-8859-1" + +/* get part of the from field to display */ + +void get_from_value(struct mailimf_single_fields * fields, + char ** from, int * is_addr) +{ + struct mailimf_mailbox * mb; + + if (fields->fld_from == NULL) { + * from = NULL; + * is_addr = 0; + return; + } + + if (clist_isempty(fields->fld_from->frm_mb_list->mb_list)) { + * from = NULL; + * is_addr = 0; + return; + } + + mb = clist_begin(fields->fld_from->frm_mb_list->mb_list)->data; + + if (mb->mb_display_name != NULL) { + * from = mb->mb_display_name; + * is_addr = 0; + } + else { + * from = mb->mb_addr_spec; + * is_addr = 1; + } +} + +/* remove all CR and LF of a string and replace them with SP */ + +void strip_crlf(char * str) +{ + char * p; + + for(p = str ; * p != '\0' ; p ++) { + if ((* p == '\n') || (* p == '\r')) + * p = ' '; + } +} + +#define MAX_OUTPUT 81 + +/* display information for one message */ + +void print_mail_info(char * prefix, mailmessage * msg) +{ + char * from; + char * subject; + char * decoded_from; + char * decoded_subject; + size_t cur_token; + int r; + int is_addr; + char * dsp_from; + char * dsp_subject; + char output[MAX_OUTPUT]; + struct mailimf_single_fields single_fields; + + is_addr = 0; + from = NULL; + subject = NULL; + + decoded_subject = NULL; + decoded_from = NULL; + + /* from field */ + + if (msg->msg_fields != NULL) + mailimf_single_fields_init(&single_fields, msg->msg_fields); + else + memset(&single_fields, 0, sizeof(single_fields)); + + get_from_value(&single_fields, &from, &is_addr); + + if (from == NULL) + decoded_from = NULL; + else { + if (!is_addr) { + cur_token = 0; + r = mailmime_encoded_phrase_parse(DEST_CHARSET, + from, strlen(from), + &cur_token, DEST_CHARSET, + &decoded_from); + if (r != MAILIMF_NO_ERROR) { + decoded_from = strdup(from); + if (decoded_from == NULL) + goto err; + } + } + else { + decoded_from = strdup(from); + if (decoded_from == NULL) { + goto err; + } + } + } + + if (decoded_from == NULL) + dsp_from = ""; + else { + dsp_from = decoded_from; + strip_crlf(dsp_from); + } + + /* subject */ + + if (single_fields.fld_subject != NULL) + subject = single_fields.fld_subject->sbj_value; + + if (subject == NULL) + decoded_subject = NULL; + else { + cur_token = 0; + r = mailmime_encoded_phrase_parse(DEST_CHARSET, + subject, strlen(subject), + &cur_token, DEST_CHARSET, + &decoded_subject); + if (r != MAILIMF_NO_ERROR) { + decoded_subject = strdup(subject); + if (decoded_subject == NULL) + goto free_from; + } + } + + if (decoded_subject == NULL) + dsp_subject = ""; + else { + dsp_subject = decoded_subject; + strip_crlf(dsp_subject); + } + + snprintf(output, MAX_OUTPUT, "%3i: %-21.21s %s%-53.53s", + msg->msg_index, dsp_from, prefix, dsp_subject); + + printf("%s\n", output); + + if (decoded_subject != NULL) + free(decoded_subject); + if (decoded_from != NULL) + free(decoded_from); + + return; + + free_from: + if (decoded_from) + free(decoded_from); + err: + {} +} Added: freeswitch/trunk/libs/libetpan/tests/frm-common.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/frm-common.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,14 @@ +#ifndef FRM_COMMON_H + +#define FRM_COMMON_H + +#include <libetpan/libetpan.h> + +void get_from_value(struct mailimf_single_fields * fields, + char ** from, int * is_addr); + +void strip_crlf(char * str); + +void print_mail_info(char * prefix, mailmessage * msg); + +#endif Added: freeswitch/trunk/libs/libetpan/tests/frm-simple.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/frm-simple.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,229 @@ +#include "option-parser.h" +#include "frm-common.h" + +#include <libetpan/libetpan.h> + +#include <stdlib.h> +#include <string.h> + +#define DEST_CHARSET "iso-8859-1" + +#define MAX_OUTPUT 81 + +/* display information for one message */ + +static void simple_print_mail_info(mailmessage * msg) +{ + char * from; + char * subject; + int is_addr; + char * dsp_from; + char * dsp_subject; + char output[MAX_OUTPUT]; + struct mailimf_single_fields single_fields; + + is_addr = 0; + from = NULL; + subject = NULL; + + if (msg->msg_fields != NULL) + mailimf_single_fields_init(&single_fields, msg->msg_fields); + else + memset(&single_fields, 0, sizeof(single_fields)); + + /* from field */ + + get_from_value(&single_fields, &from, &is_addr); + + if (from == NULL) + dsp_from = strdup(""); + else + dsp_from = strdup(from); + if (dsp_from == NULL) + goto err; + + strip_crlf(dsp_from); + + /* subject */ + + if (single_fields.fld_subject != NULL) + subject = single_fields.fld_subject->sbj_value; + + if (subject == NULL) + dsp_subject = strdup(""); + else + dsp_subject = strdup(subject); + + if (dsp_subject == NULL) + goto free_from; + + strip_crlf(dsp_subject); + + snprintf(output, MAX_OUTPUT, "%3i: %-21.21s %-53.53s\n", + msg->msg_index % 1000, dsp_from, dsp_subject); + + printf("%s\n", output); + + free(dsp_subject); + free(dsp_from); + + return; + + free_from: + free(dsp_from); + err: + {} +} + +/* get the message list and display it */ + +static void print_message_list(mailsession * session) +{ + int r; + uint32_t i; + struct mailmessage_list * env_list; + unsigned int count; + + /* get the list of messages numbers of the folder */ + + r = mailsession_get_messages_list(session, &env_list); + if (r != MAIL_NO_ERROR) { + printf("error message list\n"); + goto err; + } + + /* get fields content of these messages */ + + r = mailsession_get_envelopes_list(session, env_list); + if (r != MAIL_NO_ERROR) { + printf("error envelopes list\n"); + goto free_msg_list; + } + + /* display all the messages */ + + count = 0; + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + printf("could not fetch envelope of message %i\n", i); + } + else { + simple_print_mail_info(msg); + count ++; + } + } + printf(" %i messages\n", count); + + /* free structure */ + + mailmessage_list_free(env_list); + + return; + + free_msg_list: + mailmessage_list_free(env_list); + err: + {} +} + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + /* get and display the list of messages */ + + print_message_list(folder->fld_session); + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} + Added: freeswitch/trunk/libs/libetpan/tests/frm-tree.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/frm-tree.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,235 @@ +#include "option-parser.h" +#include "frm-common.h" + +#include <libetpan/libetpan.h> + +#include <stdlib.h> +#include <string.h> + +#define DEST_CHARSET "iso-8859-1" + +/* display tree */ + +static void +display_sub_tree(MMAPString * prefix, + struct mailmessage_tree * msg_tree, + int level, int has_next, unsigned int * pcount) +{ + carray * list; + uint32_t cur; + + if (msg_tree->node_msg != NULL) { + print_mail_info(prefix->str, msg_tree->node_msg); + (* pcount) ++; + } + + list = msg_tree->node_children; + + if (carray_count(list) != 0) { + char old_prefix[2]; + + if (level > 1) { + memcpy(old_prefix, prefix->str + prefix->len - 2, 2); + if (has_next) + memcpy(prefix->str + prefix->len - 2, "| ", 2); + else + memcpy(prefix->str + prefix->len - 2, " ", 2); + } + for(cur = 0 ; cur < carray_count(list) ; cur ++) { + int sub_has_next; + + if (cur != carray_count(list) - 1) { + if (level > 0) { + if (mmap_string_append(prefix, "+-") == NULL) + return; + } + sub_has_next = 1; + } + else { + if (level > 0) { + if (mmap_string_append(prefix, "\\-") == NULL) + return; + } + sub_has_next = 0; + } + + display_sub_tree(prefix, carray_get(list, cur), + level + 1, sub_has_next, pcount); + + if (mmap_string_truncate(prefix, prefix->len - 2) == NULL) { + return; + } + } + if (level > 1) { + memcpy(prefix->str + prefix->len - 2, old_prefix, 2); + } + } +} + +static void display_tree(struct mailmessage_tree * env_tree, + unsigned int * pcount) +{ + MMAPString * prefix; + + prefix = mmap_string_new(""); + if (prefix == NULL) + return; + + display_sub_tree(prefix, env_tree, 0, 0, pcount); + + mmap_string_free(prefix); +} + +/* get the message list and display it */ + +static void print_message_list(mailsession * session) +{ + int r; + struct mailmessage_list * env_list; + struct mailmessage_tree * env_tree; + unsigned int count; + + /* get the list of messages numbers of the folder */ + + r = mailsession_get_messages_list(session, &env_list); + if (r != MAIL_NO_ERROR) { + printf("error message list\n"); + goto err; + } + + /* get fields content of these messages */ + + r = mailsession_get_envelopes_list(session, env_list); + if (r != MAIL_NO_ERROR) { + printf("error envelopes list\n"); + goto free_msg_list; + } + + /* build threads */ + + r = mail_build_thread(MAIL_THREAD_REFERENCES_NO_SUBJECT, + DEST_CHARSET, + env_list, &env_tree, + mailthread_tree_timecomp); + if (r != MAIL_NO_ERROR) { + printf("can't build tree\n"); + goto free_msg_list; + } + + /* display message tree */ + + count = 0; + display_tree(env_tree, &count); + + printf(" %i messages\n", count); + + /* free structure */ + + mailmessage_tree_free_recursive(env_tree); + mailmessage_list_free(env_list); + + return; + + free_msg_list: + mailmessage_list_free(env_list); + err: + {} +} + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + /* get and display the list of messages */ + + print_message_list(folder->fld_session); + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} + Added: freeswitch/trunk/libs/libetpan/tests/frm.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/frm.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,159 @@ +#include "option-parser.h" +#include "frm-common.h" + +#include <libetpan/libetpan.h> + +#include <stdlib.h> +#include <string.h> + +#define DEST_CHARSET "iso-8859-1" + +/* get the message list and display it */ + +static void print_message_list(mailsession * session) +{ + int r; + uint32_t i; + struct mailmessage_list * env_list; + unsigned int count; + + /* get the list of messages numbers of the folder */ + + r = mailsession_get_messages_list(session, &env_list); + if (r != MAIL_NO_ERROR) { + printf("error message list\n"); + goto err; + } + + /* get fields content of these messages */ + + r = mailsession_get_envelopes_list(session, env_list); + if (r != MAIL_NO_ERROR) { + printf("error envelopes list\n"); + goto free_msg_list; + } + + /* display all the messages */ + + count = 0; + for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) { + mailmessage * msg; + + msg = carray_get(env_list->msg_tab, i); + + if (msg->msg_fields == NULL) { + printf("could not fetch envelope of message %i\n", i); + } + else { + print_mail_info("", msg); + count ++; + } + } + printf(" %i messages\n", count); + + /* free structure */ + + mailmessage_list_free(env_list); + + return; + + free_msg_list: + mailmessage_list_free(env_list); + err: + {} +} + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error connecting folder\n"); + goto free_folder; + } + + /* get and display the list of messages */ + + print_message_list(folder->fld_session); + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} + Added: freeswitch/trunk/libs/libetpan/tests/option-parser.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/option-parser.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,242 @@ +#define _GNU_SOURCE +#ifdef _MSC_VER +# include "../src/bsd/getopt.h" +#else +# include <getopt.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <limits.h> + +#include <libetpan/libetpan.h> + +#include "option-parser.h" + +/* + options + + --driver (pop3|imap|nntp|mbox|mh|maildir) -d + + default driver is mbox + + --server {server-name} -s + --port {port-number} -p + --tls -t + --starttls -x + --user {login} -u + --password {password} -v + --path {mailbox} -l + --apop -a + --cache {directory} -c + --flags {directory} -f +*/ + +struct storage_name { + int id; + char * name; +}; + +static struct storage_name storage_tab[] = { + {POP3_STORAGE, "pop3"}, + {IMAP_STORAGE, "imap"}, + {NNTP_STORAGE, "nntp"}, + {MBOX_STORAGE, "mbox"}, + {MH_STORAGE, "mh"}, + {MAILDIR_STORAGE, "maildir"}, +}; + +static int get_driver(char * name) +{ + int driver_type; + unsigned int i; + + driver_type = -1; + for(i = 0 ; i < sizeof(storage_tab) / sizeof(struct storage_name) ; i++) { + if (strcasecmp(name, storage_tab[i].name) == 0) { + driver_type = i; + break; + } + } + + return driver_type; +} + +int parse_options(int argc, char ** argv, + int * driver, + char ** server, int * port, int * connection_type, + char ** user, char ** password, int * auth_type, + char ** path, char ** cache_directory, + char ** flags_directory) +{ + int index; + static struct option long_options[] = { + {"driver", 1, 0, 'd'}, + {"server", 1, 0, 's'}, + {"port", 1, 0, 'p'}, + {"tls", 0, 0, 't'}, + {"starttls", 0, 0, 'x'}, + {"user", 1, 0, 'u'}, + {"password", 1, 0, 'v'}, + {"path", 1, 0, 'l'}, + {"apop", 0, 0, 'a'}, + {"cache", 1, 0, 'c'}, + {"flags", 1, 0, 'f'}, + {"debug-stream", 0, 0, 'D'}, + }; + int r; + char location[PATH_MAX]; + char * env_user; + + index = 0; + + * driver = MBOX_STORAGE; + * server = NULL; + * port = 0; + * connection_type = CONNECTION_TYPE_PLAIN; + * user = NULL; + * password = NULL; + * auth_type = POP3_AUTH_TYPE_PLAIN; + env_user = getenv("USER"); + if (env_user != NULL) { + snprintf(location, PATH_MAX, "/var/mail/%s", env_user); + * path = strdup(location); + } + else + * path = NULL; + * cache_directory = NULL; + * flags_directory = NULL; + + while (1) { + r = getopt_long(argc, argv, "d:s:p:txu:v:l:ac:f:D", long_options, &index); + + if (r == -1) + break; + + switch (r) { + case 'd': + * driver = get_driver(optarg); + break; + case 's': + if (* server != NULL) + free(* server); + * server = strdup(optarg); + break; + case 'p': + * port = strtoul(optarg, NULL, 10); + break; + case 't': + * connection_type = CONNECTION_TYPE_TLS; + break; + case 'x': + * connection_type = CONNECTION_TYPE_STARTTLS; + break; + case 'u': + if (* user != NULL) + free(* user); + * user = strdup(optarg); + break; + case 'v': + if (* password != NULL) + free(* password); + * password = strdup(optarg); + break; + case 'l': + if (* path != NULL) + free(* path); + * path = strdup(optarg); + break; + case 'a': + * auth_type = POP3_AUTH_TYPE_APOP; + break; + case 'c': + if (* cache_directory != NULL) + free(* cache_directory); + * cache_directory = strdup(optarg); + break; + case 'f': + if (* flags_directory != NULL) + free(* flags_directory); + * flags_directory = strdup(optarg); + break; + case 'D': + mailstream_debug = 1; + break; + } + } + + return 0; +} + +int init_storage(struct mailstorage * storage, + int driver, const char * server, int port, + int connection_type, const char * user, const char * password, int auth_type, + const char * path, const char * cache_directory, const char * flags_directory) +{ + int r; + int cached; + + cached = (cache_directory != NULL); + + switch (driver) { + case POP3_STORAGE: + r = pop3_mailstorage_init(storage, server, port, NULL, connection_type, + auth_type, user, password, cached, cache_directory, + flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing POP3 storage\n"); + goto err; + } + break; + + case IMAP_STORAGE: + r = imap_mailstorage_init(storage, server, port, NULL, connection_type, + IMAP_AUTH_TYPE_PLAIN, user, password, cached, cache_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing IMAP storage\n"); + goto err; + } + break; + + case NNTP_STORAGE: + r = nntp_mailstorage_init(storage, server, port, NULL, connection_type, + NNTP_AUTH_TYPE_PLAIN, user, password, cached, cache_directory, + flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing NNTP storage\n"); + goto err; + } + break; + + case MBOX_STORAGE: + r = mbox_mailstorage_init(storage, path, cached, cache_directory, + flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing mbox storage\n"); + goto err; + } + break; + + case MH_STORAGE: + r = mh_mailstorage_init(storage, path, cached, cache_directory, + flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing MH storage\n"); + goto err; + } + break; + case MAILDIR_STORAGE: + r = maildir_mailstorage_init(storage, path, cached, cache_directory, + flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing maildir storage\n"); + goto err; + } + break; + } + + return MAIL_NO_ERROR; + + err: + return r; +} Added: freeswitch/trunk/libs/libetpan/tests/option-parser.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/option-parser.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,28 @@ +#ifndef OPTION_PARSER + +#define OPTION_PARSER + +#include <libetpan/libetpan.h> + +enum { + POP3_STORAGE = 0, + IMAP_STORAGE, + NNTP_STORAGE, + MBOX_STORAGE, + MH_STORAGE, + MAILDIR_STORAGE, +}; + +int parse_options(int argc, char ** argv, + int * driver, + char ** server, int * port, int * connection_type, + char ** user, char ** password, int * auth_type, + char ** path, char ** cache_directory, + char ** flags_directory); + +int init_storage(struct mailstorage * storage, + int driver, const char * server, int port, + int connection_type, const char * user, const char * password, int auth_type, + const char * path, const char * cache_directory, const char * flags_directory); + +#endif Added: freeswitch/trunk/libs/libetpan/tests/pgp.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/pgp.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,150 @@ +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <stdlib.h> +#include <string.h> + +int get_content_of_file(char * filename, char ** p_content, size_t * p_length) +{ + int r; + void * mapped; + struct stat stat_buf; + int fd; + char * content; + + r = stat(filename, &stat_buf); + if (r < 0) + goto err; + + content = malloc(stat_buf.st_size + 1); + if (content == NULL) + goto err; + + fd = open(filename, O_RDONLY); + if (fd < 0) + goto free; + + mapped = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapped == (void *) MAP_FAILED) + goto close; + + memcpy(content, mapped, stat_buf.st_size); + content[stat_buf.st_size] = '\0'; + + munmap(mapped, stat_buf.st_size); + close(fd); + + * p_content = content; + * p_length = stat_buf.st_size; + + return 0; + + close: + close(fd); + free: + free(content); + err: + return -1; +} + +int mailmessage_encrypt(struct mailprivacy * privacy, + struct mailmessage * msg, + char * protocol, char * encryption_method) +{ + int r; + int res; + struct mailmime * mime; + struct mailmime * encrypted_mime; + struct mailmime * part_to_encrypt; + + r = mailprivacy_msg_get_bodystructure(privacy, msg, &mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + part_to_encrypt = mime->mm_data.mm_message.mm_msg_mime; + + r = mailprivacy_encrypt_msg(privacy, protocol, encryption_method, + msg, part_to_encrypt, &encrypted_mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + mime->mm_data.mm_message.mm_msg_mime = encrypted_mime; + encrypted_mime->mm_parent = mime; + part_to_encrypt->mm_parent = NULL; + mailmime_free(part_to_encrypt); + + return MAIL_NO_ERROR; + + err: + return res; +} + +int main(int argc, char ** argv) +{ + char * content; + size_t length; + mailmessage * msg; + int r; + struct mailprivacy * privacy; + int col; + + privacy = mailprivacy_new("/Users/hoa/tmp", 1); + if (privacy == NULL) { + goto err; + } + + r = mailprivacy_gnupg_init(privacy); + if (r != MAIL_NO_ERROR) { + goto free_privacy; + } + + if (argc < 2) { + fprintf(stderr, "syntax: pgp [message]\n"); + goto done_gpg; + } + + r = get_content_of_file(argv[1], &content, &length); + if (r < 0) { + fprintf(stderr, "file not found %s\n", argv[1]); + goto done_gpg; + } + + msg = data_message_init(content, length); + if (msg == NULL) { + fprintf(stderr, "unexpected error\n"); + goto free_content; + } + + r = mailmessage_encrypt(privacy, msg, "pgp", "encrypted"); + if (r != MAIL_NO_ERROR) { + fprintf(stderr, "cannot encrypt\n"); + goto free_content; + } + + col = 0; + mailmime_write(stdout, &col, msg->msg_mime); + + mailmessage_free(msg); + + free(content); + mailprivacy_gnupg_done(privacy); + mailprivacy_free(privacy); + + exit(EXIT_SUCCESS); + + free_content: + free(content); + done_gpg: + mailprivacy_gnupg_done(privacy); + free_privacy: + mailprivacy_free(privacy); + err: + exit(EXIT_FAILURE); +} Added: freeswitch/trunk/libs/libetpan/tests/readmsg-common.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/readmsg-common.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,722 @@ +#include "readmsg-common.h" + +#include <sys/stat.h> +#ifndef _MSC_VER +# include <sys/mman.h> +# include <unistd.h> +#endif +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> + +/* returns TRUE is given MIME part is a text part */ + +int etpan_mime_is_text(struct mailmime * build_info) +{ + if (build_info->mm_type == MAILMIME_SINGLE) { + if (build_info->mm_content_type != NULL) { + if (build_info->mm_content_type->ct_type->tp_type == + MAILMIME_TYPE_DISCRETE_TYPE) { + if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type == + MAILMIME_DISCRETE_TYPE_TEXT) + return 1; + } + } + else + return 1; + } + + return 0; +} + + +/* display content type */ + +int show_part_info(FILE * f, + struct mailmime_single_fields * mime_fields, + struct mailmime_content * content) +{ + char * description; + char * filename; + int col; + int r; + + description = mime_fields->fld_description; + filename = mime_fields->fld_disposition_filename; + + col = 0; + + r = fprintf(f, " [ Part "); + if (r < 0) + goto err; + + if (content != NULL) { + r = mailmime_content_type_write(f, &col, content); + if (r != MAILIMF_NO_ERROR) + goto err; + } + + if (filename != NULL) { + r = fprintf(f, " (%s)", filename); + if (r < 0) + goto err; + } + + if (description != NULL) { + r = fprintf(f, " : %s", description); + if (r < 0) + goto err; + } + + r = fprintf(f, " ]\n\n"); + if (r < 0) + goto err; + + return NO_ERROR; + + err: + return ERROR_FILE; +} + +/* + fetch the data of the mailmime_data structure whether it is a file + or a string. + + data must be freed with mmap_string_unref() +*/ + +#if 0 +static int fetch_data(struct mailmime_data * data, + char ** result, size_t * result_len) +{ + int fd; + int r; + char * text; + struct stat buf; + int res; + MMAPString * mmapstr; + + switch (data->dt_type) { + case MAILMIME_DATA_TEXT: + mmapstr = mmap_string_new_len(data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length); + if (mmapstr == NULL) { + res = ERROR_MEMORY; + goto err; + } + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return NO_ERROR; + + case MAILMIME_DATA_FILE: + fd = open(data->dt_data.dt_filename, O_RDONLY); + if (fd < 0) { + res = ERROR_FILE; + goto err; + } + + r = fstat(fd, &buf); + if (r < 0) { + res = ERROR_FILE; + goto close; + } + + if (buf.st_size != 0) { + text = mmap(NULL, buf.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (text == (char *)MAP_FAILED) { + res = ERROR_FILE; + goto close; + } + + mmapstr = mmap_string_new_len(text, buf.st_size); + if (mmapstr == NULL) { + res = r; + goto unmap; + } + + munmap(text, buf.st_size); + } + else { + mmapstr = mmap_string_new(""); + if (mmapstr == NULL) { + res = r; + goto close; + } + } + + close(fd); + + * result = mmapstr->str; + * result_len = mmapstr->len; + + return NO_ERROR; + + default: + return ERROR_INVAL; + } + + unmap: + munmap(text, buf.st_size); + close: + close(fd); + err: + return res; +} +#endif + +/* fetch message and decode if it is base64 or quoted-printable */ + +int etpan_fetch_message(mailmessage * msg_info, + struct mailmime * mime_part, + struct mailmime_single_fields * fields, + char ** result, size_t * result_len) +{ + char * data; + size_t len; + int r; + int encoding; + char * decoded; + size_t decoded_len; + size_t cur_token; + int res; + int encoded; + + encoded = 0; + + r = mailmessage_fetch_section(msg_info, + mime_part, &data, &len); + if (r != MAIL_NO_ERROR) { + res = ERROR_FETCH; + goto err; + } + + encoded = 1; + + /* decode message */ + + if (encoded) { + if (fields->fld_encoding != NULL) + encoding = fields->fld_encoding->enc_type; + else + encoding = MAILMIME_MECHANISM_8BIT; + } + else { + encoding = MAILMIME_MECHANISM_8BIT; + } + + cur_token = 0; + r = mailmime_part_parse(data, len, &cur_token, + encoding, &decoded, &decoded_len); + if (r != MAILIMF_NO_ERROR) { + res = ERROR_FETCH; + goto free; + } + + mailmessage_fetch_result_free(msg_info, data); + + * result = decoded; + * result_len = decoded_len; + + return NO_ERROR; + + free: + mailmessage_fetch_result_free(msg_info, data); + err: + return res; +} + + +/* fetch fields */ + +struct mailimf_fields * fetch_fields(mailmessage * msg_info, + struct mailmime * mime) +{ + char * data; + size_t len; + int r; + size_t cur_token; + struct mailimf_fields * fields; + + r = mailmessage_fetch_section_header(msg_info, mime, &data, &len); + if (r != MAIL_NO_ERROR) + return NULL; + + cur_token = 0; + r = mailimf_fields_parse(data, len, &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) { + mailmessage_fetch_result_free(msg_info, data); + return NULL; + } + + mailmessage_fetch_result_free(msg_info, data); + + return fields; +} + + + +#define MAX_MAIL_COL 72 + +/* write decoded mailbox */ + +static int +etpan_mailbox_write(FILE * f, int * col, + struct mailimf_mailbox * mb) +{ + int r; + + if (* col > 1) { + + if (* col + strlen(mb->mb_addr_spec) >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + * col = 1; + } + } + + if (mb->mb_display_name) { + char * decoded_from; + size_t cur_token; + + cur_token = 0; + r = mailmime_encoded_phrase_parse(DEST_CHARSET, + mb->mb_display_name, strlen(mb->mb_display_name), + &cur_token, DEST_CHARSET, + &decoded_from); + if (r != MAILIMF_NO_ERROR) { + decoded_from = strdup(mb->mb_display_name); + if (decoded_from == NULL) + return ERROR_MEMORY; + } + + r = mailimf_quoted_string_write(f, col, decoded_from, + strlen(decoded_from)); + if (r != MAILIMF_NO_ERROR) { + free(decoded_from); + return ERROR_FILE; + } + + if (* col > 1) { + + if (* col + strlen(decoded_from) + 3 >= MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) { + free(decoded_from); + return r; + } + * col = 1; + } + } + + free(decoded_from); + + r = mailimf_string_write(f, col, " <", 2); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + + r = mailimf_string_write(f, col, + mb->mb_addr_spec, strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + } + else { + r = mailimf_string_write(f, col, + mb->mb_addr_spec, strlen(mb->mb_addr_spec)); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + } + + + return NO_ERROR; + +} + +/* write decoded mailbox list */ + +int +etpan_mailbox_list_write(FILE * f, int * col, + struct mailimf_mailbox_list * mb_list) +{ + clistiter * cur; + int r; + int first; + + first = 1; + + for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_mailbox * mb; + + mb = cur->data; + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + } + else { + first = 0; + } + + r = etpan_mailbox_write(f, col, mb); + if (r != NO_ERROR) + return r; + } + + return NO_ERROR; +} + +/* write decoded group */ + +static int +etpan_group_write(FILE * f, int * col, + struct mailimf_group * group) +{ + int r; + + r = mailimf_string_write(f, col, group->grp_display_name, + strlen(group->grp_display_name)); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + + r = mailimf_string_write(f, col, ": ", 2); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + + if (group->grp_mb_list != NULL) { + r = etpan_mailbox_list_write(f, col, group->grp_mb_list); + if (r != NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, ";", 1); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + + return NO_ERROR; +} + +/* write decoded address */ + +int +etpan_address_write(FILE * f, int * col, + struct mailimf_address * addr) +{ + int r; + + switch(addr->ad_type) { + case MAILIMF_ADDRESS_MAILBOX: + r = etpan_mailbox_write(f, col, addr->ad_data.ad_mailbox); + if (r != NO_ERROR) + return r; + + break; + + case MAILIMF_ADDRESS_GROUP: + r = etpan_group_write(f, col, addr->ad_data.ad_group); + if (r != NO_ERROR) + return r; + + break; + } + + return MAILIMF_NO_ERROR; +} + +/* write decoded address list */ + +int +etpan_address_list_write(FILE * f, int * col, + struct mailimf_address_list * addr_list) +{ + clistiter * cur; + int r; + int first; + + first = 1; + + for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_address * addr; + + addr = clist_content(cur); + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return ERROR_FILE; + } + else { + first = 0; + } + + r = etpan_address_write(f, col, addr); + if (r != NO_ERROR) + return r; + } + + return NO_ERROR; +} + +/* write decoded subject */ + +static int etpan_subject_write(FILE * f, int * col, + char * subject) +{ + int r; + char * decoded_subject; + size_t cur_token; + + r = mailimf_string_write(f, col, "Subject: ", 9); + if (r != MAILIMF_NO_ERROR) { + return ERROR_FILE; + } + + cur_token = 0; + r = mailmime_encoded_phrase_parse(DEST_CHARSET, + subject, strlen(subject), + &cur_token, DEST_CHARSET, + &decoded_subject); + if (r != MAILIMF_NO_ERROR) { + decoded_subject = strdup(subject); + if (decoded_subject == NULL) + return ERROR_MEMORY; + } + + r = mailimf_string_write(f, col, decoded_subject, strlen(decoded_subject)); + if (r != MAILIMF_NO_ERROR) { + free(decoded_subject); + return ERROR_FILE; + } + + free(decoded_subject); + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + return ERROR_FILE; + } + * col = 0; + + return NO_ERROR; +} + +/* write decoded fields */ + +int fields_write(FILE * f, int * col, + struct mailimf_fields * fields) +{ + clistiter * cur; + int r; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_field * field; + + field = clist_content(cur); + + switch (field->fld_type) { + case MAILIMF_FIELD_FROM: + r = mailimf_string_write(f, col, "From: ", 6); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_mailbox_list_write(f, col, + field->fld_data.fld_from->frm_mb_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_REPLY_TO: + r = mailimf_string_write(f, col, "Reply-To: ", 10); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_address_list_write(f, col, + field->fld_data.fld_reply_to->rt_addr_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_TO: + r = mailimf_string_write(f, col, "To: ", 4); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_address_list_write(f, col, + field->fld_data.fld_to->to_addr_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_CC: + r = mailimf_string_write(f, col, "Cc: ", 4); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_address_list_write(f, col, + field->fld_data.fld_cc->cc_addr_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_BCC: + r = mailimf_string_write(f, col, "Bcc: ", 10); + if (r != MAILIMF_NO_ERROR) + goto err; + + if (field->fld_data.fld_bcc->bcc_addr_list != NULL) { + r = etpan_address_list_write(f, col, + field->fld_data.fld_bcc->bcc_addr_list); + if (r != NO_ERROR) + goto err; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_SUBJECT: + r = etpan_subject_write(f, col, field->fld_data.fld_subject->sbj_value); + if (r != MAILIMF_NO_ERROR) + goto err; + break; + + case MAILIMF_FIELD_RESENT_FROM: + r = mailimf_string_write(f, col, "Resent-From: ", 13); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_mailbox_list_write(f, col, + field->fld_data.fld_resent_from->frm_mb_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + break; + + case MAILIMF_FIELD_RESENT_TO: + r = mailimf_string_write(f, col, "Resent-To: ", 11); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_address_list_write(f, col, + field->fld_data.fld_resent_to->to_addr_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + case MAILIMF_FIELD_RESENT_CC: + r = mailimf_string_write(f, col, "Resent-Cc: ", 11); + if (r != MAILIMF_NO_ERROR) + goto err; + + r = etpan_address_list_write(f, col, + field->fld_data.fld_resent_cc->cc_addr_list); + if (r != NO_ERROR) + goto err; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + case MAILIMF_FIELD_RESENT_BCC: + r = mailimf_string_write(f, col, "Resent-Bcc: ", 12); + if (r != MAILIMF_NO_ERROR) + goto err; + + if (field->fld_data.fld_resent_bcc->bcc_addr_list != NULL) { + r = etpan_address_list_write(f, col, + field->fld_data.fld_resent_bcc->bcc_addr_list); + if (r != NO_ERROR) + goto err; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + goto err; + * col = 0; + + break; + + case MAILIMF_FIELD_ORIG_DATE: + case MAILIMF_FIELD_RESENT_DATE: + r = mailimf_field_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + goto err; + break; + + case MAILIMF_FIELD_OPTIONAL_FIELD: + if ((strcasecmp(field->fld_data.fld_optional_field->fld_name, + "X-Mailer") == 0) + || (strncasecmp(field->fld_data.fld_optional_field->fld_name, + "Resent-", 7) == 0) + || (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Newsgroups") == 0) + || (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "Followup-To") == 0) + || (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "User-Agent") == 0)) { + r = mailimf_field_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + goto err; + } + break; + + case MAILIMF_FIELD_MESSAGE_ID: + case MAILIMF_FIELD_SENDER: + case MAILIMF_FIELD_IN_REPLY_TO: + case MAILIMF_FIELD_REFERENCES: + default: + break; + } + } + + return NO_ERROR; + + err: + return ERROR_FILE; +} Added: freeswitch/trunk/libs/libetpan/tests/readmsg-common.h ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/readmsg-common.h Wed Dec 20 15:28:56 2006 @@ -0,0 +1,37 @@ +#ifndef READMSG_COMMON_H + +#define READMSG_COMMON_H + +#include <libetpan/libetpan.h> + +#define DEST_CHARSET "iso-8859-1" + +enum { +/* SEB */ +#ifndef NO_ERROR + NO_ERROR, +#endif + ERROR_FILE = 1, + ERROR_MEMORY = 2, + ERROR_INVAL = 3, + ERROR_FETCH = 4, +}; + +int etpan_mime_is_text(struct mailmime * build_info); + +int show_part_info(FILE * f, + struct mailmime_single_fields * mime_fields, + struct mailmime_content * content); + +int etpan_fetch_message(mailmessage * msg_info, + struct mailmime * mime_part, + struct mailmime_single_fields * fields, + char ** result, size_t * result_len); + +struct mailimf_fields * fetch_fields(mailmessage * msg_info, + struct mailmime * mime); + +int fields_write(FILE * f, int * col, + struct mailimf_fields * fields); + +#endif Added: freeswitch/trunk/libs/libetpan/tests/readmsg-simple.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/readmsg-simple.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,133 @@ +#include <unistd.h> +#include <string.h> +#include <stdlib.h> + +#include <libetpan/libetpan.h> + +#include "option-parser.h" + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + while (optind < argc) { + mailmessage * msg; + uint32_t msg_num; + char * data; + size_t size; + + msg_num = strtoul(argv[optind], NULL, 10); + + r = mailsession_get_message(folder->fld_session, msg_num, &msg); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found **\n", msg_num); + optind ++; + continue; + } + + r = mailmessage_fetch(msg, &data, &size); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found - %s **\n", msg_num, + maildriver_strerror(r)); + mailmessage_free(msg); + optind ++; + continue; + } + + fwrite(data, 1, size, stdout); + + mailmessage_fetch_result_free(msg, data); + + mailmessage_free(msg); + + optind ++; + } + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} Added: freeswitch/trunk/libs/libetpan/tests/readmsg-uid.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/readmsg-uid.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,133 @@ +#include <unistd.h> +#include <string.h> +#include <stdlib.h> + +#include <libetpan/libetpan.h> + +#include "option-parser.h" + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + while (optind < argc) { + mailmessage * msg; + char * data; + size_t size; + char * uid; + + uid = argv[optind]; + + r = mailsession_get_message_by_uid(folder->fld_session, uid, &msg); + if (r != MAIL_NO_ERROR) { + printf("** message %s not found **\n", uid); + optind ++; + continue; + } + + r = mailmessage_fetch(msg, &data, &size); + if (r != MAIL_NO_ERROR) { + printf("** message %s not found - %s **\n", uid, + maildriver_strerror(r)); + mailmessage_free(msg); + optind ++; + continue; + } + + fwrite(data, 1, size, stdout); + + mailmessage_fetch_result_free(msg, data); + + mailmessage_free(msg); + + optind ++; + } + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} Added: freeswitch/trunk/libs/libetpan/tests/readmsg.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/readmsg.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,359 @@ +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <string.h> +#include <stdlib.h> + +#include <libetpan/charconv.h> +#include <libetpan/libetpan.h> + +#include "option-parser.h" +#include "readmsg-common.h" +#ifdef _MSC_VER +# include "../src/bsd/getopt.h" +#endif + +/* render message */ + +static int etpan_render_mime(FILE * f, mailmessage * msg_info, + struct mailmime * mime) +{ + int r; + clistiter * cur; + int col; + int text; + int show; + struct mailmime_single_fields fields; + int res; + + mailmime_single_fields_init(&fields, mime->mm_mime_fields, + mime->mm_content_type); + + text = etpan_mime_is_text(mime); + + r = show_part_info(f, &fields, mime->mm_content_type); + if (r != NO_ERROR) { + res = r; + goto err; + } + + switch(mime->mm_type) { + case MAILMIME_SINGLE: + show = 0; + if (text) + show = 1; + + if (show) { + char * data; + size_t len; + char * converted; + size_t converted_len; + char * source_charset; + size_t write_len; + + /* viewable part */ + + r = etpan_fetch_message(msg_info, mime, + &fields, &data, &len); + if (r != NO_ERROR) { + res = r; + goto err; + } + + source_charset = fields.fld_content_charset; + if (source_charset == NULL) + source_charset = DEST_CHARSET; + + r = charconv_buffer(source_charset, DEST_CHARSET, + data, len, &converted, &converted_len); + if (r != MAIL_CHARCONV_NO_ERROR) { + + r = fprintf(f, "[ error converting charset from %s to %s ]\n", + source_charset, DEST_CHARSET); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + + write_len = fwrite(data, 1, len, f); + if (write_len != len) { + mailmime_decoded_part_free(data); + res = r; + goto err; + } + } + else { + write_len = fwrite(converted, 1, converted_len, f); + if (write_len != len) { + charconv_buffer_free(converted); + mailmime_decoded_part_free(data); + res = r; + goto err; + } + + charconv_buffer_free(converted); + } + + write_len = fwrite("\r\n\r\n", 1, 4, f); + if (write_len < 4) { + mailmime_decoded_part_free(data); + res = ERROR_FILE; + goto err; + } + + mailmime_decoded_part_free(data); + } + else { + /* not viewable part */ + + r = fprintf(f, " (not shown)\n\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + break; + + case MAILMIME_MULTIPLE: + + if (strcasecmp(mime->mm_content_type->ct_subtype, "alternative") == 0) { + struct mailmime * prefered_body; + int prefered_score; + + /* case of multiple/alternative */ + + /* + we choose the better part, + alternative preference : + + text/plain => score 3 + text/xxx => score 2 + other => score 1 + */ + + prefered_body = NULL; + prefered_score = 0; + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * submime; + int score; + + score = 1; + submime = clist_content(cur); + if (etpan_mime_is_text(submime)) + score = 2; + + if (submime->mm_content_type != NULL) { + if (strcasecmp(submime->mm_content_type->ct_subtype, "plain") == 0) + score = 3; + } + + if (score > prefered_score) { + prefered_score = score; + prefered_body = submime; + } + } + + if (prefered_body != NULL) { + r = etpan_render_mime(f, msg_info, prefered_body); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + else { + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + + r = etpan_render_mime(f, msg_info, clist_content(cur)); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + } + + break; + + case MAILMIME_MESSAGE: + + if (mime->mm_data.mm_message.mm_fields != NULL) { + struct mailimf_fields * fields; + + if (msg_info != NULL) { + fields = fetch_fields(msg_info, mime); + if (fields == NULL) { + res = ERROR_FETCH; + goto err; + } + + col = 0; + r = fields_write(f, &col, fields); + if (r != NO_ERROR) { + mailimf_fields_free(fields); + res = r; + goto err; + } + + mailimf_fields_free(fields); + } + else { + col = 0; + r = fields_write(f, &col, mime->mm_data.mm_message.mm_fields); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + r = fprintf(f, "\r\n"); + if (r < 0) { + res = ERROR_FILE; + goto err; + } + } + + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + r = etpan_render_mime(f, msg_info, mime->mm_data.mm_message.mm_msg_mime); + if (r != NO_ERROR) { + res = r; + goto err; + } + } + + break; + } + + return NO_ERROR; + + err: + return res; +} + + +int main(int argc, char ** argv) +{ + int r; + int driver; + char * server; + int port; + int connection_type; + char * user; + char * password; + int auth_type; + char * path; + char * cache_directory; + char * flags_directory; + struct mailstorage * storage; + int cached; + struct mailfolder * folder; + + /* get options */ + + r = parse_options(argc, argv, + &driver, &server, &port, &connection_type, + &user, &password, &auth_type, + &path, &cache_directory, &flags_directory); + + cached = (cache_directory != NULL); + + /* build the storage structure */ + + storage = mailstorage_new(NULL); + if (storage == NULL) { + printf("error initializing storage\n"); + goto free_opt; + } + + r = init_storage(storage, driver, server, port, connection_type, + user, password, auth_type, path, cache_directory, flags_directory); + if (r != MAIL_NO_ERROR) { + printf("error initializing storage\n"); + goto free_opt; + } + + /* get the folder structure */ + + folder = mailfolder_new(storage, path, NULL); + if (folder == NULL) { + printf("error initializing folder\n"); + goto free_storage; + } + + r = mailfolder_connect(folder); + if (r != MAIL_NO_ERROR) { + printf("error initializing folder\n"); + goto free_folder; + } + + while (optind < argc) { + mailmessage * msg; + uint32_t msg_num; + struct mailmime * mime; + + msg_num = strtoul(argv[optind], NULL, 10); + + r = mailsession_get_message(folder->fld_session, msg_num, &msg); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found ** - %s\n", msg_num, + maildriver_strerror(r)); + optind ++; + continue; + } + + r = mailmessage_get_bodystructure(msg, &mime); + if (r != MAIL_NO_ERROR) { + printf("** message %i not found - %s **\n", msg_num, + maildriver_strerror(r)); + mailmessage_free(msg); + optind ++; + continue; + } + + r = etpan_render_mime(stdout, msg, mime); + + mailmessage_free(msg); + + optind ++; + } + + mailfolder_free(folder); + mailstorage_free(storage); + + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + + return 0; + + free_folder: + mailfolder_free(folder); + free_storage: + mailstorage_free(storage); + free_opt: + if (server != NULL) + free(server); + if (user != NULL) + free(user); + if (password != NULL) + free(password); + if (path != NULL) + free(path); + if (cache_directory != NULL) + free(cache_directory); + if (flags_directory != NULL) + free(flags_directory); + return -1; +} Added: freeswitch/trunk/libs/libetpan/tests/smime.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/smime.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,177 @@ +#include <libetpan/libetpan.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <stdlib.h> +#include <string.h> + +int get_content_of_file(char * filename, char ** p_content, size_t * p_length) +{ + int r; + void * mapped; + struct stat stat_buf; + int fd; + char * content; + + r = stat(filename, &stat_buf); + if (r < 0) + goto err; + + content = malloc(stat_buf.st_size + 1); + if (content == NULL) + goto err; + + fd = open(filename, O_RDONLY); + if (fd < 0) + goto free; + + mapped = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapped == (void *) MAP_FAILED) + goto close; + + memcpy(content, mapped, stat_buf.st_size); + content[stat_buf.st_size] = '\0'; + + munmap(mapped, stat_buf.st_size); + close(fd); + + * p_content = content; + * p_length = stat_buf.st_size; + + return 0; + + close: + close(fd); + free: + free(content); + err: + return -1; +} + +int mailmessage_encrypt(struct mailprivacy * privacy, + struct mailmessage * msg, + char * protocol, char * encryption_method) +{ + int r; + int res; + struct mailmime * mime; + struct mailmime * encrypted_mime; + struct mailmime * part_to_encrypt; + + r = mailprivacy_msg_get_bodystructure(privacy, msg, &mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + part_to_encrypt = mime->mm_data.mm_message.mm_msg_mime; + + r = mailprivacy_encrypt_msg(privacy, protocol, encryption_method, + msg, part_to_encrypt, &encrypted_mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + + mime->mm_data.mm_message.mm_msg_mime = encrypted_mime; + encrypted_mime->mm_parent = mime; + part_to_encrypt->mm_parent = NULL; + mailmime_free(part_to_encrypt); + + return MAIL_NO_ERROR; + + err: + return res; +} + +int main(int argc, char ** argv) +{ + char * content; + size_t length; + mailmessage * msg; + int r; + struct mailprivacy * privacy; + int col; + + privacy = mailprivacy_new("/Users/hoa/tmp", 1); + if (privacy == NULL) { + goto err; + } + + r = mailprivacy_smime_init(privacy); + if (r != MAIL_NO_ERROR) { + goto free_privacy; + } + + mailprivacy_smime_set_cert_dir(privacy, + "/Users/hoa/LibEtPan/libetpan/tests/keys/cert"); + + mailprivacy_smime_set_CA_dir(privacy, + "/Users/hoa/LibEtPan/libetpan/tests/keys/ca"); + + mailprivacy_smime_set_private_keys_dir(privacy, + "/Users/hoa/LibEtPan/libetpan/tests/keys/private"); + + mailprivacy_smime_set_encryption_id(privacy, "dinh.vh@euro.apple.com", "coin"); + + if (argc < 2) { + fprintf(stderr, "syntax: pgp [message]\n"); + goto done_gpg; + } + + r = get_content_of_file(argv[1], &content, &length); + if (r < 0) { + fprintf(stderr, "file not found %s\n", argv[1]); + goto done_gpg; + } + + msg = data_message_init(content, length); + if (msg == NULL) { + fprintf(stderr, "unexpected error\n"); + goto free_content; + } + + r = mailmessage_encrypt(privacy, msg, "smime", "signed"); + if (r != MAIL_NO_ERROR) { + { + clist * id_list; + unsigned int i; + clistiter * iter; + + id_list = mailprivacy_smime_encryption_id_list(privacy, msg); + if (id_list != NULL) { + for(iter = clist_begin(id_list) ; iter != NULL ; iter = clist_next(iter)) { + char * str; + + str = clist_content(iter); + fprintf(stderr, "%s\n", str); + } + } + } + + fprintf(stderr, "cannot encrypt\n"); + goto free_content; + } + + col = 0; + mailmime_write(stdout, &col, msg->msg_mime); + + mailmessage_free(msg); + + free(content); + mailprivacy_gnupg_done(privacy); + mailprivacy_free(privacy); + + exit(EXIT_SUCCESS); + + free_content: + free(content); + done_gpg: + mailprivacy_smime_done(privacy); + free_privacy: + mailprivacy_free(privacy); + err: + exit(EXIT_FAILURE); +} Added: freeswitch/trunk/libs/libetpan/tests/smtpsend.c ============================================================================== --- (empty file) +++ freeswitch/trunk/libs/libetpan/tests/smtpsend.c Wed Dec 20 15:28:56 2006 @@ -0,0 +1,292 @@ +/* + * Simple Mail Submission Agent using SMTP with libEtPan! + * TODO: Full sendmail like interface + */ + +#include <libetpan/libetpan.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#ifdef _MSC_VER +# include "win_etpan.h" +# include "../src/bsd/getopt.h" +# define STDIN_FILENO _fileno( stdin) +#else +# include <netdb.h> +# include <netinet/in.h> +# include <sys/socket.h> +# include <sys/mman.h> +# include <unistd.h> +# include <sys/ioctl.h> +# include <pwd.h> + +# define _GNU_SOURCE +# include <getopt.h> +#endif + +/* globals */ +char *smtp_server; +uint16_t smtp_port = 25; +char *smtp_user; +char *smtp_password; +char *smtp_from; +int smtp_tls = 0; +int smtp_esmtp = 1; + +struct mem_message { + char *data; + size_t len; + MMAPString *mstring; +}; + +#define BLOCKSIZE 4096 + +int collect(struct mem_message *message) { + struct stat sb; + int len; + + memset(message, 0, sizeof(struct mem_message)); + +#ifndef MMAP_UNAVAILABLE + /* if stdin is a file whose size is known, try to mmap it */ + if (!fstat(0, &sb) && S_ISREG(sb.st_mode) && sb.st_size >= 0) { + message->len = sb.st_size; + if ((message->data = mmap(NULL, message->len, PROT_READ, MAP_SHARED, + STDIN_FILENO, 0)) != MAP_FAILED) + return 0; + } +#endif + + /* read the buffer from stdin by blocks, until EOF or error. + save the message in a mmap_string */ + if ((message->mstring = mmap_string_sized_new(BLOCKSIZE)) == NULL) { + perror("mmap_string_new"); + goto error; + } + message->len = 0; + + while ((len = read(STDIN_FILENO, + message->mstring->str + message->len, BLOCKSIZE)) > 0) { + message->len += len; + /* reserve room for next block */ + if ((mmap_string_set_size(message->mstring, + message->len + BLOCKSIZE)) == NULL) { + perror("mmap_string_set_size"); + goto error; + } + } + + if (len == 0) { + message->data = message->mstring->str; + return 0; /* OK */ + } + + perror("read"); + + error: + if (message->mstring != NULL) + mmap_string_free(message->mstring); + return -1; +} + +char *guessfrom() { +#ifndef _MSC_VER + uid_t uid; + struct passwd *pw; + char hostname[256]; + int len; + char *gfrom; + + if (gethostname(hostname, sizeof(hostname))) { + perror("gethostname"); + return NULL; + } + hostname[sizeof(hostname) - 1] = '\0'; + + uid = getuid(); + pw = getpwuid(uid); + + len = ((pw != NULL) ? strlen(pw->pw_name) : 12) + + strlen(hostname) + 2; + + if ((gfrom = malloc(len)) == NULL) { + perror("malloc"); + return NULL; + } + if (pw != NULL && pw->pw_name != NULL) + snprintf(gfrom, len, "%s@%s", pw->pw_name, hostname); + else + snprintf(gfrom, len, "#%u@%s", uid, hostname); + return gfrom; +#else + return NULL; +#endif +} + +void release(struct mem_message *message) { + if (message->mstring != NULL) + mmap_string_free(message->mstring); +#ifndef MMAP_UNAVAILABLE + else if (message->data != NULL) + munmap(message->data, message->len); +#endif +} + +int send_message(char *data, size_t len, char**rcpts) { + int s = -1; + int ret; + char **r; + int esmtp = 0; + mailsmtp *smtp = NULL; + + if ((smtp = mailsmtp_new(0, NULL)) == NULL) { + perror("mailsmtp_new"); + goto error; + } + + /* first open the stream */ + if ((ret = mailsmtp_socket_connect(smtp, + (smtp_server != NULL ? smtp_server : "localhost"), + smtp_port)) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_socket_connect: %s\n", mailsmtp_strerror(ret)); + goto error; + } + + /* then introduce ourselves */ + if (smtp_esmtp && (ret = mailesmtp_ehlo(smtp)) == MAILSMTP_NO_ERROR) + esmtp = 1; + else if (!smtp_esmtp || ret == MAILSMTP_ERROR_NOT_IMPLEMENTED) + ret = mailsmtp_helo(smtp); + if (ret != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_helo: %s\n", mailsmtp_strerror(ret)); + goto error; + } + + if (esmtp && smtp_tls && + (ret = mailsmtp_socket_starttls(smtp)) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_starttls: %s\n", mailsmtp_strerror(ret)); + goto error; + } + + if (esmtp && smtp_user != NULL && + (ret = mailsmtp_auth(smtp, smtp_user, + (smtp_password != NULL) ? smtp_password : "")) + != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_auth: %s: %s\n", smtp_user, mailsmtp_strerror(ret)); + goto error; + } + + /* source */ + if ((ret = (esmtp ? + mailesmtp_mail(smtp, smtp_from, 1, "etPanSMTPTest") : + mailsmtp_mail(smtp, smtp_from))) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_mail: %s, %s\n", smtp_from, mailsmtp_strerror(ret)); + goto error; + } + + /* recipients */ + for (r = rcpts; *r != NULL; r++) { + if ((ret = (esmtp ? + mailesmtp_rcpt(smtp, *r, + MAILSMTP_DSN_NOTIFY_FAILURE|MAILSMTP_DSN_NOTIFY_DELAY, + NULL) : + mailsmtp_rcpt(smtp, *r))) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_rcpt: %s: %s\n", *r, mailsmtp_strerror(ret)); + goto error; + } + } + + /* message */ + if ((ret = mailsmtp_data(smtp)) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_data: %s\n", mailsmtp_strerror(ret)); + goto error; + } + if ((ret = mailsmtp_data_message(smtp, data, len)) != MAILSMTP_NO_ERROR) { + fprintf(stderr, "mailsmtp_data_message: %s\n", mailsmtp_strerror(ret)); + goto error; + } + mailsmtp_free(smtp); + return 0; + + error: + if (smtp != NULL) + mailsmtp_free(smtp); + if (s >= 0) + close(s); + return -1; +} + +int main(int argc, char **argv) { + struct mem_message message; + int index, r; + + static struct option long_options[] = { + {"server", 1, 0, 's'}, + {"port", 1, 0, 'p'}, + {"user", 1, 0, 'u'}, + {"password", 1, 0, 'v'}, + {"from", 1, 0, 'f'}, + {"tls", 0, 0, 'S'}, + {"no-esmtp", 0, 0, 'E'}, + }; + + while(1) { + if ((r = getopt_long(argc, argv, "s:p:u:v:f:SE", long_options, &index)) < 0) + break; + switch (r) { + case 's': + if (smtp_server != NULL) + free(smtp_server); + smtp_server = strdup(optarg); + break; + case 'p': + smtp_port = (uint16_t) strtoul(optarg, NULL, 10); + break; + case 'u': + if (smtp_user != NULL) + free(smtp_user); + smtp_user = strdup(optarg); + break; + case 'v': + if (smtp_password != NULL) + free(smtp_password); + smtp_password = strdup(optarg); + break; + case 'f': + if (smtp_from != NULL) + free(smtp_from); + smtp_from = strdup(optarg); + break; + case 'S': + smtp_tls = 1; + break; + case 'E': + smtp_esmtp = 0; + break; + } + } + + argc -= optind; + argv += optind; + + if (argc < 1) { + fprintf(stderr, "usage: smtpsend [-f from] [-u user] [-v password] [-s server] [-p port] [-S] <rcpts>...\n"); + return EXIT_FAILURE; + } + + if (smtp_from == NULL && (smtp_from = guessfrom()) == NULL) { + fprintf(stderr, "can't guess a valid from, please use -f option.\n"); + return EXIT_FAILURE; + } + + /* reads message from stdin */ + if (collect(&message)) + return EXIT_FAILURE; + + send_message(message.data, message.len, argv); + + release(&message); + return EXIT_SUCCESS; +}
participants (1)
-
Freeswitch SVN